From 40a4e8d6acc3f23973936cc76df9af8aac784d56 Mon Sep 17 00:00:00 2001 From: wangcongowen Date: Sat, 28 Mar 2020 11:50:28 -0400 Subject: [PATCH 01/12] CHanged End of Line char to unix format --- tools/preamble | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/preamble b/tools/preamble index 42fdc81c9..8f2dba0b0 100755 --- a/tools/preamble +++ b/tools/preamble @@ -1,3 +1,4 @@ +# Change the format of End of Line char cd "$(dirname "$0")" DATE=$(date -u "+%Y-%m-%d %H:%M:%SZ") From 0280049abb49f0e74da61cd809cb0ca4cb6e8516 Mon Sep 17 00:00:00 2001 From: wangcongowen Date: Thu, 2 Apr 2020 00:53:13 -0400 Subject: [PATCH 02/12] Added plugin Touch --- css/annotator.touch.css | 641 +++++++++++++++++++++++++++ demo.html | 18 +- package-lock.json | 578 ++++++++++++++++++++++++ pkg/Makefile | 21 +- src/annotator.coffee | 4 +- src/plugin/touch/annotator.touch.css | 641 +++++++++++++++++++++++++++ src/plugin/touch/touch.coffee | 417 +++++++++++++++++ src/plugin/touch/touch_editor.coffee | 177 ++++++++ src/plugin/touch/touch_utils.coffee | 131 ++++++ src/plugin/touch/touch_viewer.coffee | 77 ++++ 10 files changed, 2697 insertions(+), 8 deletions(-) create mode 100644 css/annotator.touch.css create mode 100644 package-lock.json create mode 100644 src/plugin/touch/annotator.touch.css create mode 100644 src/plugin/touch/touch.coffee create mode 100644 src/plugin/touch/touch_editor.coffee create mode 100644 src/plugin/touch/touch_utils.coffee create mode 100644 src/plugin/touch/touch_viewer.coffee diff --git a/css/annotator.touch.css b/css/annotator.touch.css new file mode 100644 index 000000000..db8d26f76 --- /dev/null +++ b/css/annotator.touch.css @@ -0,0 +1,641 @@ +.annotator-viewer .annotator-touch-controls .annotator-edit::after { + /* Assign the image once to ensure data uri is not repeated. */ + background-image: url(../images/icon-sprite.png); +} + +.annotator-selection-handle::after { + background-image: url(../images/handle.png); +} + +.annotator-button::after { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAEiCAYAAAD0w4JOAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RkREQjU5NUUzRTREMTFFMUJCQThENjQ1NDg5Q0U3NUYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RkREQjU5NUYzRTREMTFFMUJCQThENjQ1NDg5Q0U3NUYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDMkY4NEM4QjNERkExMUUxQkJBOEQ2NDU0ODlDRTc1RiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDMkY4NEM4QzNERkExMUUxQkJBOEQ2NDU0ODlDRTc1RiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PoUNah0AABE5SURBVHja7JwJWFXX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'); +} + +/* Generic Touch Widget Styles */ +.annotator-touch-widget { + font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; + border: 1px solid rgba(0, 0, 0, 0.8); + background: rgba(0, 0, 0, 0.85); + background: -webkit-gradient( + linear, left top, left bottom, + from(rgba(57, 57, 57, 0.85)), + color-stop(0.5, rgba(58, 58, 58, 0.85)), + color-stop(0.5, rgba(0, 0, 0, 0.85)), + to(rgba(0, 0, 0, 0.85)) + ); + background: -moz-linear-gradient( + -90deg, + from(rgba(57, 57, 57, 0.85)), + color-stop(0.5, rgba(58, 58, 58, 0.85)), + color-stop(0.5, rgba(0, 0, 0, 0.85)) 50%, + to(rgba(0, 0, 0, 0.85)) + ); + background: -webkit-linear-gradient( + -90deg, + from(rgba(57, 57, 57, 0.85)), + color-stop(0.5, rgba(58, 58, 58, 0.85)) 50%, + color-stop(0.5, rgba(0, 0, 0, 0.85)) 50%, + to(rgba(0, 0, 0, 0.85)) + ); + background: linear-gradient( + to bottom, + from(rgba(57, 57, 57, 0.85)), + color-stop(0.5, rgba(58, 58, 58, 0.85)) 50%, + color-stop(0.5, rgba(0, 0, 0, 0.85)) 50%, + to(rgba(0, 0, 0, 0.85)) + ); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + -ms-border-radius: 4px; + -o-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4); + -moz-box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4); + -ms-box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4); + -o-box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4); + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4); + /* Removes the tap outline on elements that have bound touch events */ + -webkit-tap-highlight-color: transparent; +} + +.annotator-touch-widget-inner { + background: #efefef; + border: 1px solid rgba(0, 0, 0, 0.8); + margin: 7px; + padding: 6px; + line-height: 0; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + -ms-border-radius: 3px; + -o-border-radius: 3px; + border-radius: 3px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.8); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.8); + -ms-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.8); + -o-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.8); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.8); +} + +.annotator-touch-widget .annotator-button { + cursor: pointer; + font-size: 16px; + line-height: 44px; + padding-left: 40px; + padding-right: 20px; + -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1); + -ms-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1); + -o-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1); + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} + +.annotator-touch-widget .annotator-button[disabled] { + opacity: 0.3; + cursor: default; +} + +.annotator-touch-widget .annotator-button::after { + left: 15px; +} + +.annotator-touch-widget .annotator-add::after, +.annotator-touch-widget .annotator-add:hover::after, +.annotator-touch-widget .annotator-add:focus::after, +.annotator-touch-widget .annotator-add.annotator-focus::after { + margin-top: -7px; + background-position: 0 -270px; +} + +/* Adder Styles */ + +.annotator-touch-controls { + position: fixed; + bottom: 15px; + right: 15px; + min-width: auto; +} + +.annotator-touch-controls.annotator-touch-hide { + right: -9999em; + opacity: 0; + -webkit-transition: opacity 0.2s 0 ease-in, right 0s 0.3s linear; + -moz-transition: opacity 0.2s 0 ease-in, right 0s 0.3s linear; + -ms-transition: opacity 0.2s 0 ease-in, right 0s 0.3s linear; + -o-transition: opacity 0.2s 0 ease-in, right 0s 0.3s linear; + transition: opacity 0.2s 0 ease-in, right 0s 0.3s linear; +} + +.annotator-touch-controls .annotator-button { + line-height: 56px; +} + +/* Viewer Overrides*/ + +.annotator-touch-viewer .annotator-widget { + min-width: 380px; +} + +.annotator-touch-viewer div { + padding: 12px; +} + +.annotator-touch-viewer div:first-of-type { + font-size: 18px; + padding-top: 20px; + padding-bottom: 20px; +} + +.annotator-touch-viewer .annotator-touch-controls { + position: absolute; + top: 0; + left: auto; + right: 0; + display: none; + background: rgba(255, 255, 255, 0.6); + background: -webkit-gradient( + linear, right top, left top, + from(rgba(255, 255, 255, 0.8)), + color-stop(0.9, rgba(255, 255, 255, 0.8)), + to(rgba(255, 255, 255, 0)) + ); + background: -moz-linear-gradient( + 0deg, + from(rgba(255, 255, 255, 0.8)) 90%, + to(rgba(255, 255, 255, 0)) + ); + background: -webkit-linear-gradient( + 0deg, + from(rgba(255, 255, 255, 0.8)) 90%, + to(rgba(255, 255, 255, 0)) + ); + background: linear-gradient( + to bottom, + from(rgba(255, 255, 255, 0.8)) 90%, + to(rgba(255, 255, 255, 0)) + ); + -webkit-box-pack: end; + -webkit-box-align: center; + -webkit-box-orient: horizontal; + -moz-box-pack: end; + -moz-box-align: center; + -moz-box-orient: horizontal; + box-pack: end; + box-align: center; + box-orient: horizontal; + padding: 10px; + bottom: 0; + padding: 0 10px 0 20px; +} + +.annotator-touch-viewer li.annotator-visible .annotator-touch-controls { + display: -webkit-box; + display: -moz-box; + display: box; +} + +.annotator-touch-viewer .annotator-touch-controls button { + line-height: 44px; + padding-left: 40px; + padding-right: 20px; + margin-left: 6px; +} + +.annotator-touch-viewer .annotator-touch-controls .annotator-edit::after { + background-position: 0 -15px; +} + +.annotator-touch-viewer .annotator-touch-controls .annotator-edit:hover::after, +.annotator-touch-viewer .annotator-touch-controls .annotator-edit:focus::after, +.annotator-touch-viewer .annotator-touch-controls .annotator-edit:active::after, +.annotator-touch-viewer .annotator-touch-controls .annotator-edit.annotator-focus::after { + background-position: 0 -30px; +} + +.annotator-touch-viewer .annotator-touch-controls button::after { + left: 15px; +} + +/* Editor Overrides */ + +.annotator-touch-editor { + position: fixed; + top: -1000px !important; + left: 0 !important; + right: 0; + bottom: -1000px; + padding: 1000px 0; + width: 100%; + height: 100%; + background: rgba(255, 255, 255, 0.6); + display: -webkit-box; + display: -moz-box; + display: box; + -webkit-box-pack: center; + -webkit-box-align: center; + -moz-box-pack: center; + -moz-box-align: center; + box-pack: center; + box-align: center; +} + +.annotator-touch-editor .annotator-touch-widget { + pointer-events: all; + position: relative; + width: 80%; + max-width: 680px; +} + +.annotator-touch-editor .annotator-touch-widget-inner { + position: static; + width: auto; + padding: 0; + background: #fff; +} + +.annotator-touch-editor .annotator-widget::after { + display: none; +} + +.annotator-touch-editor .annotator-widget .annotator-item { + border-top-color: rgba(0, 0, 0, 0.15); +} + +.annotator-touch-editor .annotator-widget .annotator-item, +.annotator-touch-editor.annotator-editor .annotator-item label, +.annotator-touch-editor.annotator-editor .annotator-item input, +.annotator-touch-editor.annotator-editor .annotator-item textarea { + font-size: 18px; +} + +.annotator-touch-editor.annotator-editor .annotator-item input, +.annotator-touch-editor.annotator-editor .annotator-item label { + line-height: 30px; + margin-left: 8px; +} + +.annotator-touch-editor.annotator-editor .annotator-item input[checkbox] { + font-size: large; +} + +.annotator-touch-editor .annotator-widget .annotator-item:first-child textarea { + font-size: 18px; + background-color: #fff; + -webkit-border-radius: 3px 3px 0 0; + -moz-border-radius: 3px 3px 0 0; + -o-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0; +} + +.annotator-touch-editor .annotator-resize { + display: none; +} + +.annotator-touch-editor .annotator-controls { + padding: 7px; + background-color: #efefef; + background-image: none; +} + +.annotator-touch-editor .annotator-item-quote { + font-size: 16px; + line-height: 1.2; + border-color: #cebfa2; + background-color: #fbfae9; + color: #a58129; + padding: 10px 7px; +} + +.annotator-item-quote span { + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: #a58129; + font-family: Georgia, serif; +} + +.annotator-item-quote.annotator-touch-expand span { + overflow: visible; + text-overflow: inherit; + white-space: inherit; +} + +.annotator-item-quote button { + font-size: 14px; + line-height: 44px; + margin-top: -13px; + float: right; + text-transform: uppercase; + font-weight: bold; + color: #a58129; + border: none; + background: none; + margin-left: 10px; + cursor: pointer; +} + +.annotator-button::after { + background-repeat: no-repeat; +} + +.annotator-button { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + position: relative; + display: inline-block; + padding: 0 6px 0 22px; + color: rgb(54, 54, 54); + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.75); + text-decoration: none; + line-height: 24px; + font-size: 12px; + font-weight: bold; + border: 1px solid rgb(162, 162, 162); + background-color: rgb(212, 212, 212); + background-image: -webkit-gradient( + linear, left top, left bottom, + from(rgb(245, 245, 245)), + color-stop(0.5, rgb(210, 210, 210)), + color-stop(0.5, rgb(190, 190, 190)), + to(rgb(210, 210, 210)) + ); + background-image: -moz-linear-gradient( + -90deg, + rgb(245, 245, 245), + rgb(210, 210, 210) 50%, + rgb(190, 190, 190) 50%, + rgb(210, 210, 210) + ); + background-image: -webkit-linear-gradient( + -90deg, + rgb(245, 245, 245), + rgb(210, 210, 210) 50%, + rgb(190, 190, 190) 50%, + rgb(210, 210, 210) + ); + background-image: linear-gradient( + to bottom, + rgb(245, 245, 245), + rgb(210, 210, 210) 50%, + rgb(190, 190, 190) 50%, + rgb(210, 210, 210) + ); + -webkit-box-shadow: + inset 0 0 5px rgba(255, 255, 255, 0.2), + inset 0 0 1px rgba(255, 255, 255, 0.8); + -moz-box-shadow: + inset 0 0 5px rgba(255, 255, 255, 0.2), + inset 0 0 1px rgba(255, 255, 255, 0.8); + -o-box-shadow: + inset 0 0 5px rgba(255, 255, 255, 0.2), + inset 0 0 1px rgba(255, 255, 255, 0.8); + box-shadow: + inset 0 0 5px rgba(255, 255, 255, 0.2), + inset 0 0 1px rgba(255, 255, 255, 0.8); + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + -o-border-radius: 5px; + border-radius: 5px; +} + +.annotator-button::after { + position: absolute; + top: 50%; + left: 5px; + display: block; + content: ""; + width: 15px; + height: 15px; + margin-top: -7px; + background-position: 0 -90px; +} + +.annotator-button:hover, +.annotator-button:focus, +.annotator-button.annotator-focus { + outline: none; + border-color: rgb(67, 90, 160); + background-color: rgb(56, 101, 249); + background-image: -webkit-gradient( + linear, left top, left bottom, + from(rgb(118, 145, 251)), + color-stop(0.5, rgb(80, 117, 251)), + color-stop(0.5, rgb(56, 101, 249)), + to(rgb(54, 101, 250)) + ); + background-image: -moz-linear-gradient( + -90deg, + rgb(118, 145, 251), + rgb(80, 117, 251) 50%, + rgb(56, 101, 249) 50%, + rgb(54, 101, 250) + ); + background-image: -webkit-linear-gradient( + -90deg, + rgb(118, 145, 251), + rgb(80, 117, 251) 50%, + rgb(56, 101, 249) 50%, + rgb(54, 101, 250) + ); + background-image: linear-gradient( + to bottom, + rgb(118, 145, 251), + rgb(80, 117, 251) 50%, + rgb(56, 101, 249) 50%, + rgb(54, 101, 250) + ); + color: rgb(255, 255, 255); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.42); +} + +.annotator-button:hover::after, +.annotator-button:focus::after { + margin-top: -8px; + background-position: 0 -105px; +} + +.annotator-button:active { + border-color: rgb(112, 12, 73); + background-color: rgb(209, 46, 142); + background-image: -webkit-gradient( + linear, left top, left bottom, + from(rgb(252, 124, 202)), + color-stop(0.5, rgb(232, 93, 178)), + color-stop(0.5, rgb(209, 46, 142)), + to(rgb(255, 0, 156)) + ); + background-image: -moz-linear-gradient( + -90deg, + rgb(252, 124, 202), + rgb(232, 93, 178) 50%, + rgb(209, 46, 142) 50%, + rgb(255, 0, 156) + ); + background-image: -webkit-linear-gradient( + -90deg, + rgb(252, 124, 202), + rgb(232, 93, 178) 50%, + rgb(209, 46, 142) 50%, + rgb(255, 0, 156) + ); + background-image: linear-gradient( + to bottom, + rgb(252, 124, 202), + rgb(232, 93, 178) 50%, + rgb(209, 46, 142) 50%, + rgb(255, 0, 156) + ); +} + +.annotator-button.annotator-save::after { + background-position: 0 -120px; +} + +.annotator-button.annotator-save::after, +.annotator-button.annotator-save:focus::after, +.annotator-button.annotator-save.annotator-focus::after { + margin-top: -8px; + background-position: 0 -135px; +} + +/* Icon only button styles */ + +[data-annotator-use-icons] .annotator-touch-widget .annotator-button { + /* width & overflow is required by Android WebKit */ + width: 1px; + overflow: hidden; + text-indent: -999em; + padding-left: 25px; +} + +[data-annotator-use-icons] .annotator-touch-controls .annotator-button { + padding-left: 35px; +} + +[data-annotator-use-icons] .annotator-touch-controls .annotator-button::after { + left: 20px; +} + +[data-annotator-use-icons] .annotator-touch-viewer .annotator-touch-controls button { + padding-left: 25px; + text-indent: -9000em; +} + +[data-annotator-use-icons] .annotator-touch-viewer .annotator-touch-controls button::after { + left: 15px; +} + +[data-annotator-use-icons] .annotator-touch-viewer .annotator-widget { + min-width: 320px; +} + +/* Highlighter Selection Styles */ + +.annotator-selection-handle { + cursor: pointer; + display: block; + position: absolute; + width: 44px; + height: 44px; + top: 0; + left: 0; + padding: 0; + margin-left: -22px; + margin-top: -22px; + border-radius: 50%; + /* Removes the tap outline on elements that have bound touch events */ + -webkit-tap-highlight-color: transparent; +} + +.annotator-selection-handle::after { + content: ""; + display: block; + width: 20px; + height: 20px; + position: absolute; + left: 50%; + margin-left: -10px; + bottom: -5px; + background-position: 0 0; + background-repeat: no-repeat; +} + +.annotator-selection-start::after { + top: -5px; + bottom: auto; + background-position: 0 -20px; +} + +.annotator-selection-hide .annotator-selection-handle { + display: none; +} + +/* Styles for smaller screens */ + +@media only screen and (max-width: 480px) { + .annotator-touch-viewer { + left: 0 !important; + width: 100%; + background: none; + min-width: 0; + border: none; + } + + .annotator-touch-viewer .annotator-widget { + position: static; + left: 0; + width: 100%; + height: auto; + min-width: 0; + -webkit-box-sizing: border-box; + -webkit-border-radius: none; + border-radius: none; + } + + .annotator-touch-viewer .annotator-widget::after { + display: none; + } + + .annotator-touch-editor { + border: none; + -webkit-box-align: start; + -moz-box-align: start; + box-align: start; + } + + .annotator-touch-editor .annotator-touch-widget { + width: 100%; + max-width: auto; + margin: 0; + border-color: #333; + border-left: none; + border-right: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + -ms-box-shadow: none; + -o-box-shadow: none; + box-shadow: none; + } + + .annotator-touch-editor .annotator-touch-widget-inner { + width: 100%; + max-width: auto; + margin: 0; + border: 0; + } + + .annotator-touch-editor .annotator-controls { + border-bottom: 1px solid #D4D4D4; + } + + .annotator-touch-editor .annotator-touch-widget, + .annotator-touch-editor .annotator-touch-widget-inner, + .annotator-touch-editor .annotator-touch-widget .annotator-item:first-child textarea, + .annotator-touch-editor .annotator-controls { + border-radius: 0; + } +} diff --git a/demo.html b/demo.html index d375eb369..8390ce871 100644 --- a/demo.html +++ b/demo.html @@ -2,11 +2,12 @@ + JS annotation test - + @@ -38,6 +39,13 @@ + + + + + + + @@ -85,8 +93,12 @@

Header Level 3

$('#airlock').annotator() .annotator('addPlugin', 'Permissions') .annotator('addPlugin', 'Markdown') - .annotator('addPlugin', 'Tags'); - + .annotator('addPlugin', 'Tags') + .annotator('addPlugin', 'Touch', { + force: location.search.indexOf('force') > -1, + useHighlighter: location.search.indexOf('highlighter') > -1 + }); + $('#airlock').data('annotator').plugins['Permissions'].setUser("Joe Bloggs"); } }); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..403100b2a --- /dev/null +++ b/package-lock.json @@ -0,0 +1,578 @@ +{ + "name": "annotator", + "version": "1.2.10", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "beholder": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/beholder/-/beholder-0.1.3.tgz", + "integrity": "sha1-LfgH8aFYJlI2p0/TIEwzu0g+nS4=", + "dev": true, + "requires": { + "async": "~0.2.5", + "glob": "~3.2.7", + "minimatch": "~0.2.9" + }, + "dependencies": { + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true, + "requires": { + "inherits": "2", + "minimatch": "0.3" + }, + "dependencies": { + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + } + } + } + } + }, + "buffer-crc32": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.1.tgz", + "integrity": "sha1-vj5TgvwCttYySVasGvmKqYsIU0w=", + "dev": true + }, + "buster-core": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/buster-core/-/buster-core-0.6.4.tgz", + "integrity": "sha1-J79rrWdCROpyDzEdkAoMoct4YFA=", + "dev": true + }, + "buster-format": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/buster-format/-/buster-format-0.5.6.tgz", + "integrity": "sha1-K4bDIuz14bCubm55Bev884fSq5U=", + "dev": true, + "requires": { + "buster-core": "=0.6.4" + } + }, + "bytes": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-0.2.0.tgz", + "integrity": "sha1-qtM+wU49wsp06OfUUfm6BTrU96A=", + "dev": true + }, + "chai": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-1.5.0.tgz", + "integrity": "sha1-mvogA8/LcyiW+ClWjuMIpny+zPA=", + "dev": true + }, + "coffee-script": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.7.1.tgz", + "integrity": "sha1-YplqhheAx15tUGnROCJyO3NAS/w=", + "dev": true, + "requires": { + "mkdirp": "~0.3.5" + } + }, + "coffeebarx": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/coffeebarx/-/coffeebarx-0.0.3.tgz", + "integrity": "sha1-HxcQT26RnQ9QosuzZ5b2iq1MKN4=", + "dev": true, + "requires": { + "beholder": "~0.1.2", + "coffee-script": "~1.6.2", + "commander": "~1.1.1", + "glob": "~3.1.21", + "mkdirp": "~0.3.5", + "source-map": "~0.1.22", + "uglify-js": "~2.2.5", + "xcolor": "~0.1.0" + }, + "dependencies": { + "coffee-script": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.6.3.tgz", + "integrity": "sha1-Y1XTLPGwTN/2tITl5xF4Ky8MOb4=", + "dev": true + }, + "uglify-js": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz", + "integrity": "sha1-puAqcNg5eSuXgEiLe4sYTAlcmcc=", + "dev": true, + "requires": { + "optimist": "~0.3.5", + "source-map": "~0.1.7" + } + } + } + }, + "commander": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-1.1.1.tgz", + "integrity": "sha1-UNFlGGiuYOzP8KLZ80WVN2vGsEE=", + "dev": true, + "requires": { + "keypress": "0.1.x" + } + }, + "connect": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/connect/-/connect-2.10.1.tgz", + "integrity": "sha1-28aTklJ7NpNSKdwp43IkmuusZEg=", + "dev": true, + "requires": { + "buffer-crc32": "0.2.1", + "bytes": "0.2.0", + "cookie": "0.1.0", + "cookie-signature": "1.0.1", + "debug": "*", + "fresh": "0.2.0", + "methods": "0.0.1", + "multiparty": "2.2.0", + "negotiator": "0.2.8", + "pause": "0.0.1", + "qs": "0.6.5", + "raw-body": "0.0.3", + "send": "0.1.4", + "uid2": "0.0.2" + } + }, + "cookie": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.0.tgz", + "integrity": "sha1-kOtGndzpBchm3mh+/EMTHYgB+dA=", + "dev": true + }, + "cookie-signature": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.1.tgz", + "integrity": "sha1-ROByFIrwHm6OJK+/EmkNaK5pjss=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "diff": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.0.2.tgz", + "integrity": "sha1-Suc/Gu6Nb89ITxoc53zmUdm38Mk=", + "dev": true + }, + "fresh": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.2.0.tgz", + "integrity": "sha1-v9lALPPfEsSkwxDHn5mj3eE9NKc=", + "dev": true + }, + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "~1.2.0", + "inherits": "1", + "minimatch": "~0.2.11" + }, + "dependencies": { + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + } + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "growl": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.7.0.tgz", + "integrity": "sha1-3i1mE20ALhErpw8/EMMc98NQsto=", + "dev": true + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "iso8601": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/iso8601/-/iso8601-1.1.1.tgz", + "integrity": "sha1-jKy8/nwEvYxGA5rS6Jj8F7A6bkM=" + }, + "jade": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", + "dev": true, + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, + "dependencies": { + "commander": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", + "dev": true + }, + "mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", + "dev": true + } + } + }, + "jwt-simple": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/jwt-simple/-/jwt-simple-0.5.6.tgz", + "integrity": "sha512-40aUybvhH9t2h71ncA1/1SbtTNCVZHgsTsTgqPUxGWDmUDrXyDf2wMNQKEbdBjbf4AI+fQhbECNTV6lWxQKUzg==" + }, + "keypress": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz", + "integrity": "sha1-SjGI1CkbZrT2XtuZ+AaqmuKTWSo=", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "mapcat": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/mapcat/-/mapcat-0.2.0.tgz", + "integrity": "sha1-pKYiF+em6zy1VynNcXgHM1sF9c0=", + "dev": true, + "requires": { + "optimist": "~0.3.5", + "source-map": "~0.1.3" + } + }, + "methods": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/methods/-/methods-0.0.1.tgz", + "integrity": "sha1-J3yQ+L7zlwlkWoNxxRw7bGSOBow=", + "dev": true + }, + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + }, + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "dev": true + }, + "mocha": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-1.9.0.tgz", + "integrity": "sha1-FBBUsTywPOXOWa7OPWXVygG43wo=", + "dev": true, + "requires": { + "commander": "0.6.1", + "debug": "*", + "diff": "1.0.2", + "growl": "1.7.x", + "jade": "0.26.3", + "mkdirp": "0.3.3", + "ms": "0.3.0" + }, + "dependencies": { + "commander": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", + "dev": true + }, + "mkdirp": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.3.tgz", + "integrity": "sha1-WV4lHBNww6aLqyE20ONIuBBa3xM=", + "dev": true + }, + "ms": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.3.0.tgz", + "integrity": "sha1-A+3DSNYT5mpWSGz9rFO8vomcvWE=", + "dev": true + } + } + }, + "mocha-phantomjs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mocha-phantomjs/-/mocha-phantomjs-2.0.1.tgz", + "integrity": "sha1-sDw58xAh12vVuScolmRewN3QpRs=", + "dev": true, + "requires": { + "commander": "~ 1.0.5", + "mocha": "1.7.x" + }, + "dependencies": { + "commander": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/commander/-/commander-1.0.5.tgz", + "integrity": "sha1-RXKVu5duOI6d0NtS3kMz4knz2Iw=", + "dev": true, + "requires": { + "keypress": "0.1.x" + } + }, + "growl": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.6.1.tgz", + "integrity": "sha1-xNm7ro+aVyKV2gYrA81z4e8uFLI=", + "dev": true + }, + "mkdirp": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.3.tgz", + "integrity": "sha1-WV4lHBNww6aLqyE20ONIuBBa3xM=", + "dev": true + }, + "mocha": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-1.7.4.tgz", + "integrity": "sha1-WEIOiSO0TcVUggGyHFLrqNT/MM0=", + "dev": true, + "requires": { + "commander": "0.6.1", + "debug": "*", + "diff": "1.0.2", + "growl": "1.6.x", + "jade": "0.26.3", + "mkdirp": "0.3.3", + "ms": "0.3.0" + }, + "dependencies": { + "commander": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", + "dev": true + } + } + }, + "ms": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.3.0.tgz", + "integrity": "sha1-A+3DSNYT5mpWSGz9rFO8vomcvWE=", + "dev": true + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "multiparty": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-2.2.0.tgz", + "integrity": "sha1-pWfCrwAK0i3I8qZT2Rl4rh9TFvQ=", + "dev": true, + "requires": { + "readable-stream": "~1.1.9", + "stream-counter": "~0.2.0" + } + }, + "negotiator": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.2.8.tgz", + "integrity": "sha1-rf0gejh1xNNwlXKcLnwoPFui7nI=", + "dev": true + }, + "optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", + "dev": true, + "requires": { + "wordwrap": "~0.0.2" + } + }, + "pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=", + "dev": true + }, + "qs": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.5.tgz", + "integrity": "sha1-KUsmjksNQlD23eGbO4s0k13/FO8=", + "dev": true + }, + "range-parser": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-0.0.4.tgz", + "integrity": "sha1-wEJ//vUcEKy6B4KkbJYC50T/Ygs=", + "dev": true + }, + "raw-body": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-0.0.3.tgz", + "integrity": "sha1-DLPrIs7RymB9Mt2P2Upus4Pz64o=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "send": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/send/-/send-0.1.4.tgz", + "integrity": "sha1-vnDY0b4B3mGCGvE3gLUDRaT3Gr0=", + "dev": true, + "requires": { + "debug": "*", + "fresh": "0.2.0", + "mime": "~1.2.9", + "range-parser": "0.0.4" + } + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "sinon": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.6.0.tgz", + "integrity": "sha1-V3sBfYaUO4xCU31awuhjcw9YzJs=", + "dev": true, + "requires": { + "buster-format": "~0.5" + } + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": ">=0.0.4" + } + }, + "stream-counter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/stream-counter/-/stream-counter-0.2.0.tgz", + "integrity": "sha1-3tJmVWMZyLDiIoErnPOyb6fZR94=", + "dev": true, + "requires": { + "readable-stream": "~1.1.8" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "uglify-js": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.3.6.tgz", + "integrity": "sha1-+gmEdwtCi3qbKoBY9GNV0U/vIRo=", + "dev": true, + "requires": { + "async": "~0.2.6", + "optimist": "~0.3.5", + "source-map": "~0.1.7" + } + }, + "uglifycss": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/uglifycss/-/uglifycss-0.0.5.tgz", + "integrity": "sha1-25ZSu/P+1Q0um26TDig4Cg/Dpbc=", + "dev": true + }, + "uid2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.2.tgz", + "integrity": "sha1-EH+xVcgsETZiB5ftTIjPKwj2qrg=", + "dev": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "xcolor": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/xcolor/-/xcolor-0.1.0.tgz", + "integrity": "sha1-A4W8GjuLPry/Ivd1NlHCC2RiYxA=", + "dev": true + } + } +} diff --git a/pkg/Makefile b/pkg/Makefile index a794240c6..8cf119447 100644 --- a/pkg/Makefile +++ b/pkg/Makefile @@ -25,7 +25,14 @@ PLUGINS=\ plugin/permissions.coffee \ plugin/store.coffee \ plugin/tags.coffee \ - plugin/unsupported.coffee + plugin/unsupported.coffee \ + plugin/touch/touch.coffee \ + plugin/touch/touch_editor.coffee \ + plugin/touch/touch_utils.coffee \ + plugin/touch/touch_viewer.coffee + +PLUGINS_RESOURCES=\ + plugin/touch/annotator.touch.css ANNOTATOR_FULL=\ $(ANNOTATOR) \ @@ -37,7 +44,11 @@ ANNOTATOR_FULL=\ plugin/filter.coffee \ plugin/markdown.coffee \ plugin/tags.coffee \ - plugin/kitchensink.coffee + plugin/kitchensink.coffee \ + plugin/touch/touch.coffee \ + plugin/touch/touch_editor.coffee \ + plugin/touch/touch_utils.coffee \ + plugin/touch/touch_viewer.coffee BOOKMARKLET=\ $(ANNOTATOR) \ @@ -51,13 +62,17 @@ BOOKMARKLET=\ BOOKMARKLET_CFG=../contrib/bookmarklet/config.json BOOKMARKLET_SRC=../contrib/bookmarklet/src/bookmarklet.js -all: annotator plugins annotator-full bookmarklet +all: annotator plugins plugins-resources annotator-full bookmarklet annotator: annotator.min.js annotator.min.css PLUGIN_NAMES=$(notdir $(PLUGINS)) plugins: $(addprefix annotator.,$(PLUGIN_NAMES:.coffee=.min.js)) +plugins-resources: + @echo "Plugin resource:" ../src/$(PLUGINS_RESOURCES) + @cp ../src/$(PLUGINS_RESOURCES) ../css/`echo $(PLUGINS_RESOURCES) | sed 's:.*/::'` + annotator-full: annotator-full.min.js _preamble.map: diff --git a/src/annotator.coffee b/src/annotator.coffee index 766d4cb30..a354ecc2d 100644 --- a/src/annotator.coffee +++ b/src/annotator.coffee @@ -1,9 +1,9 @@ # Selection and range creation reference for the following code: # http://www.quirksmode.org/dom/range_intro.html -# +# # I've removed any support for IE TextRange (see commit d7085bf2 for code) # for the moment, having no means of testing it. - + # Store a reference to the current Annotator object. _Annotator = this.Annotator diff --git a/src/plugin/touch/annotator.touch.css b/src/plugin/touch/annotator.touch.css new file mode 100644 index 000000000..db8d26f76 --- /dev/null +++ b/src/plugin/touch/annotator.touch.css @@ -0,0 +1,641 @@ +.annotator-viewer .annotator-touch-controls .annotator-edit::after { + /* Assign the image once to ensure data uri is not repeated. */ + background-image: url(../images/icon-sprite.png); +} + +.annotator-selection-handle::after { + background-image: url(../images/handle.png); +} + +.annotator-button::after { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAEiCAYAAAD0w4JOAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RkREQjU5NUUzRTREMTFFMUJCQThENjQ1NDg5Q0U3NUYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RkREQjU5NUYzRTREMTFFMUJCQThENjQ1NDg5Q0U3NUYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDMkY4NEM4QjNERkExMUUxQkJBOEQ2NDU0ODlDRTc1RiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDMkY4NEM4QzNERkExMUUxQkJBOEQ2NDU0ODlDRTc1RiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PoUNah0AABE5SURBVHja7JwJWFXX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'); +} + +/* Generic Touch Widget Styles */ +.annotator-touch-widget { + font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; + border: 1px solid rgba(0, 0, 0, 0.8); + background: rgba(0, 0, 0, 0.85); + background: -webkit-gradient( + linear, left top, left bottom, + from(rgba(57, 57, 57, 0.85)), + color-stop(0.5, rgba(58, 58, 58, 0.85)), + color-stop(0.5, rgba(0, 0, 0, 0.85)), + to(rgba(0, 0, 0, 0.85)) + ); + background: -moz-linear-gradient( + -90deg, + from(rgba(57, 57, 57, 0.85)), + color-stop(0.5, rgba(58, 58, 58, 0.85)), + color-stop(0.5, rgba(0, 0, 0, 0.85)) 50%, + to(rgba(0, 0, 0, 0.85)) + ); + background: -webkit-linear-gradient( + -90deg, + from(rgba(57, 57, 57, 0.85)), + color-stop(0.5, rgba(58, 58, 58, 0.85)) 50%, + color-stop(0.5, rgba(0, 0, 0, 0.85)) 50%, + to(rgba(0, 0, 0, 0.85)) + ); + background: linear-gradient( + to bottom, + from(rgba(57, 57, 57, 0.85)), + color-stop(0.5, rgba(58, 58, 58, 0.85)) 50%, + color-stop(0.5, rgba(0, 0, 0, 0.85)) 50%, + to(rgba(0, 0, 0, 0.85)) + ); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + -ms-border-radius: 4px; + -o-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4); + -moz-box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4); + -ms-box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4); + -o-box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4); + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4); + /* Removes the tap outline on elements that have bound touch events */ + -webkit-tap-highlight-color: transparent; +} + +.annotator-touch-widget-inner { + background: #efefef; + border: 1px solid rgba(0, 0, 0, 0.8); + margin: 7px; + padding: 6px; + line-height: 0; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + -ms-border-radius: 3px; + -o-border-radius: 3px; + border-radius: 3px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.8); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.8); + -ms-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.8); + -o-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.8); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.8); +} + +.annotator-touch-widget .annotator-button { + cursor: pointer; + font-size: 16px; + line-height: 44px; + padding-left: 40px; + padding-right: 20px; + -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1); + -ms-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1); + -o-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1); + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} + +.annotator-touch-widget .annotator-button[disabled] { + opacity: 0.3; + cursor: default; +} + +.annotator-touch-widget .annotator-button::after { + left: 15px; +} + +.annotator-touch-widget .annotator-add::after, +.annotator-touch-widget .annotator-add:hover::after, +.annotator-touch-widget .annotator-add:focus::after, +.annotator-touch-widget .annotator-add.annotator-focus::after { + margin-top: -7px; + background-position: 0 -270px; +} + +/* Adder Styles */ + +.annotator-touch-controls { + position: fixed; + bottom: 15px; + right: 15px; + min-width: auto; +} + +.annotator-touch-controls.annotator-touch-hide { + right: -9999em; + opacity: 0; + -webkit-transition: opacity 0.2s 0 ease-in, right 0s 0.3s linear; + -moz-transition: opacity 0.2s 0 ease-in, right 0s 0.3s linear; + -ms-transition: opacity 0.2s 0 ease-in, right 0s 0.3s linear; + -o-transition: opacity 0.2s 0 ease-in, right 0s 0.3s linear; + transition: opacity 0.2s 0 ease-in, right 0s 0.3s linear; +} + +.annotator-touch-controls .annotator-button { + line-height: 56px; +} + +/* Viewer Overrides*/ + +.annotator-touch-viewer .annotator-widget { + min-width: 380px; +} + +.annotator-touch-viewer div { + padding: 12px; +} + +.annotator-touch-viewer div:first-of-type { + font-size: 18px; + padding-top: 20px; + padding-bottom: 20px; +} + +.annotator-touch-viewer .annotator-touch-controls { + position: absolute; + top: 0; + left: auto; + right: 0; + display: none; + background: rgba(255, 255, 255, 0.6); + background: -webkit-gradient( + linear, right top, left top, + from(rgba(255, 255, 255, 0.8)), + color-stop(0.9, rgba(255, 255, 255, 0.8)), + to(rgba(255, 255, 255, 0)) + ); + background: -moz-linear-gradient( + 0deg, + from(rgba(255, 255, 255, 0.8)) 90%, + to(rgba(255, 255, 255, 0)) + ); + background: -webkit-linear-gradient( + 0deg, + from(rgba(255, 255, 255, 0.8)) 90%, + to(rgba(255, 255, 255, 0)) + ); + background: linear-gradient( + to bottom, + from(rgba(255, 255, 255, 0.8)) 90%, + to(rgba(255, 255, 255, 0)) + ); + -webkit-box-pack: end; + -webkit-box-align: center; + -webkit-box-orient: horizontal; + -moz-box-pack: end; + -moz-box-align: center; + -moz-box-orient: horizontal; + box-pack: end; + box-align: center; + box-orient: horizontal; + padding: 10px; + bottom: 0; + padding: 0 10px 0 20px; +} + +.annotator-touch-viewer li.annotator-visible .annotator-touch-controls { + display: -webkit-box; + display: -moz-box; + display: box; +} + +.annotator-touch-viewer .annotator-touch-controls button { + line-height: 44px; + padding-left: 40px; + padding-right: 20px; + margin-left: 6px; +} + +.annotator-touch-viewer .annotator-touch-controls .annotator-edit::after { + background-position: 0 -15px; +} + +.annotator-touch-viewer .annotator-touch-controls .annotator-edit:hover::after, +.annotator-touch-viewer .annotator-touch-controls .annotator-edit:focus::after, +.annotator-touch-viewer .annotator-touch-controls .annotator-edit:active::after, +.annotator-touch-viewer .annotator-touch-controls .annotator-edit.annotator-focus::after { + background-position: 0 -30px; +} + +.annotator-touch-viewer .annotator-touch-controls button::after { + left: 15px; +} + +/* Editor Overrides */ + +.annotator-touch-editor { + position: fixed; + top: -1000px !important; + left: 0 !important; + right: 0; + bottom: -1000px; + padding: 1000px 0; + width: 100%; + height: 100%; + background: rgba(255, 255, 255, 0.6); + display: -webkit-box; + display: -moz-box; + display: box; + -webkit-box-pack: center; + -webkit-box-align: center; + -moz-box-pack: center; + -moz-box-align: center; + box-pack: center; + box-align: center; +} + +.annotator-touch-editor .annotator-touch-widget { + pointer-events: all; + position: relative; + width: 80%; + max-width: 680px; +} + +.annotator-touch-editor .annotator-touch-widget-inner { + position: static; + width: auto; + padding: 0; + background: #fff; +} + +.annotator-touch-editor .annotator-widget::after { + display: none; +} + +.annotator-touch-editor .annotator-widget .annotator-item { + border-top-color: rgba(0, 0, 0, 0.15); +} + +.annotator-touch-editor .annotator-widget .annotator-item, +.annotator-touch-editor.annotator-editor .annotator-item label, +.annotator-touch-editor.annotator-editor .annotator-item input, +.annotator-touch-editor.annotator-editor .annotator-item textarea { + font-size: 18px; +} + +.annotator-touch-editor.annotator-editor .annotator-item input, +.annotator-touch-editor.annotator-editor .annotator-item label { + line-height: 30px; + margin-left: 8px; +} + +.annotator-touch-editor.annotator-editor .annotator-item input[checkbox] { + font-size: large; +} + +.annotator-touch-editor .annotator-widget .annotator-item:first-child textarea { + font-size: 18px; + background-color: #fff; + -webkit-border-radius: 3px 3px 0 0; + -moz-border-radius: 3px 3px 0 0; + -o-border-radius: 3px 3px 0 0; + border-radius: 3px 3px 0 0; +} + +.annotator-touch-editor .annotator-resize { + display: none; +} + +.annotator-touch-editor .annotator-controls { + padding: 7px; + background-color: #efefef; + background-image: none; +} + +.annotator-touch-editor .annotator-item-quote { + font-size: 16px; + line-height: 1.2; + border-color: #cebfa2; + background-color: #fbfae9; + color: #a58129; + padding: 10px 7px; +} + +.annotator-item-quote span { + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: #a58129; + font-family: Georgia, serif; +} + +.annotator-item-quote.annotator-touch-expand span { + overflow: visible; + text-overflow: inherit; + white-space: inherit; +} + +.annotator-item-quote button { + font-size: 14px; + line-height: 44px; + margin-top: -13px; + float: right; + text-transform: uppercase; + font-weight: bold; + color: #a58129; + border: none; + background: none; + margin-left: 10px; + cursor: pointer; +} + +.annotator-button::after { + background-repeat: no-repeat; +} + +.annotator-button { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + position: relative; + display: inline-block; + padding: 0 6px 0 22px; + color: rgb(54, 54, 54); + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.75); + text-decoration: none; + line-height: 24px; + font-size: 12px; + font-weight: bold; + border: 1px solid rgb(162, 162, 162); + background-color: rgb(212, 212, 212); + background-image: -webkit-gradient( + linear, left top, left bottom, + from(rgb(245, 245, 245)), + color-stop(0.5, rgb(210, 210, 210)), + color-stop(0.5, rgb(190, 190, 190)), + to(rgb(210, 210, 210)) + ); + background-image: -moz-linear-gradient( + -90deg, + rgb(245, 245, 245), + rgb(210, 210, 210) 50%, + rgb(190, 190, 190) 50%, + rgb(210, 210, 210) + ); + background-image: -webkit-linear-gradient( + -90deg, + rgb(245, 245, 245), + rgb(210, 210, 210) 50%, + rgb(190, 190, 190) 50%, + rgb(210, 210, 210) + ); + background-image: linear-gradient( + to bottom, + rgb(245, 245, 245), + rgb(210, 210, 210) 50%, + rgb(190, 190, 190) 50%, + rgb(210, 210, 210) + ); + -webkit-box-shadow: + inset 0 0 5px rgba(255, 255, 255, 0.2), + inset 0 0 1px rgba(255, 255, 255, 0.8); + -moz-box-shadow: + inset 0 0 5px rgba(255, 255, 255, 0.2), + inset 0 0 1px rgba(255, 255, 255, 0.8); + -o-box-shadow: + inset 0 0 5px rgba(255, 255, 255, 0.2), + inset 0 0 1px rgba(255, 255, 255, 0.8); + box-shadow: + inset 0 0 5px rgba(255, 255, 255, 0.2), + inset 0 0 1px rgba(255, 255, 255, 0.8); + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + -o-border-radius: 5px; + border-radius: 5px; +} + +.annotator-button::after { + position: absolute; + top: 50%; + left: 5px; + display: block; + content: ""; + width: 15px; + height: 15px; + margin-top: -7px; + background-position: 0 -90px; +} + +.annotator-button:hover, +.annotator-button:focus, +.annotator-button.annotator-focus { + outline: none; + border-color: rgb(67, 90, 160); + background-color: rgb(56, 101, 249); + background-image: -webkit-gradient( + linear, left top, left bottom, + from(rgb(118, 145, 251)), + color-stop(0.5, rgb(80, 117, 251)), + color-stop(0.5, rgb(56, 101, 249)), + to(rgb(54, 101, 250)) + ); + background-image: -moz-linear-gradient( + -90deg, + rgb(118, 145, 251), + rgb(80, 117, 251) 50%, + rgb(56, 101, 249) 50%, + rgb(54, 101, 250) + ); + background-image: -webkit-linear-gradient( + -90deg, + rgb(118, 145, 251), + rgb(80, 117, 251) 50%, + rgb(56, 101, 249) 50%, + rgb(54, 101, 250) + ); + background-image: linear-gradient( + to bottom, + rgb(118, 145, 251), + rgb(80, 117, 251) 50%, + rgb(56, 101, 249) 50%, + rgb(54, 101, 250) + ); + color: rgb(255, 255, 255); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.42); +} + +.annotator-button:hover::after, +.annotator-button:focus::after { + margin-top: -8px; + background-position: 0 -105px; +} + +.annotator-button:active { + border-color: rgb(112, 12, 73); + background-color: rgb(209, 46, 142); + background-image: -webkit-gradient( + linear, left top, left bottom, + from(rgb(252, 124, 202)), + color-stop(0.5, rgb(232, 93, 178)), + color-stop(0.5, rgb(209, 46, 142)), + to(rgb(255, 0, 156)) + ); + background-image: -moz-linear-gradient( + -90deg, + rgb(252, 124, 202), + rgb(232, 93, 178) 50%, + rgb(209, 46, 142) 50%, + rgb(255, 0, 156) + ); + background-image: -webkit-linear-gradient( + -90deg, + rgb(252, 124, 202), + rgb(232, 93, 178) 50%, + rgb(209, 46, 142) 50%, + rgb(255, 0, 156) + ); + background-image: linear-gradient( + to bottom, + rgb(252, 124, 202), + rgb(232, 93, 178) 50%, + rgb(209, 46, 142) 50%, + rgb(255, 0, 156) + ); +} + +.annotator-button.annotator-save::after { + background-position: 0 -120px; +} + +.annotator-button.annotator-save::after, +.annotator-button.annotator-save:focus::after, +.annotator-button.annotator-save.annotator-focus::after { + margin-top: -8px; + background-position: 0 -135px; +} + +/* Icon only button styles */ + +[data-annotator-use-icons] .annotator-touch-widget .annotator-button { + /* width & overflow is required by Android WebKit */ + width: 1px; + overflow: hidden; + text-indent: -999em; + padding-left: 25px; +} + +[data-annotator-use-icons] .annotator-touch-controls .annotator-button { + padding-left: 35px; +} + +[data-annotator-use-icons] .annotator-touch-controls .annotator-button::after { + left: 20px; +} + +[data-annotator-use-icons] .annotator-touch-viewer .annotator-touch-controls button { + padding-left: 25px; + text-indent: -9000em; +} + +[data-annotator-use-icons] .annotator-touch-viewer .annotator-touch-controls button::after { + left: 15px; +} + +[data-annotator-use-icons] .annotator-touch-viewer .annotator-widget { + min-width: 320px; +} + +/* Highlighter Selection Styles */ + +.annotator-selection-handle { + cursor: pointer; + display: block; + position: absolute; + width: 44px; + height: 44px; + top: 0; + left: 0; + padding: 0; + margin-left: -22px; + margin-top: -22px; + border-radius: 50%; + /* Removes the tap outline on elements that have bound touch events */ + -webkit-tap-highlight-color: transparent; +} + +.annotator-selection-handle::after { + content: ""; + display: block; + width: 20px; + height: 20px; + position: absolute; + left: 50%; + margin-left: -10px; + bottom: -5px; + background-position: 0 0; + background-repeat: no-repeat; +} + +.annotator-selection-start::after { + top: -5px; + bottom: auto; + background-position: 0 -20px; +} + +.annotator-selection-hide .annotator-selection-handle { + display: none; +} + +/* Styles for smaller screens */ + +@media only screen and (max-width: 480px) { + .annotator-touch-viewer { + left: 0 !important; + width: 100%; + background: none; + min-width: 0; + border: none; + } + + .annotator-touch-viewer .annotator-widget { + position: static; + left: 0; + width: 100%; + height: auto; + min-width: 0; + -webkit-box-sizing: border-box; + -webkit-border-radius: none; + border-radius: none; + } + + .annotator-touch-viewer .annotator-widget::after { + display: none; + } + + .annotator-touch-editor { + border: none; + -webkit-box-align: start; + -moz-box-align: start; + box-align: start; + } + + .annotator-touch-editor .annotator-touch-widget { + width: 100%; + max-width: auto; + margin: 0; + border-color: #333; + border-left: none; + border-right: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; + -ms-box-shadow: none; + -o-box-shadow: none; + box-shadow: none; + } + + .annotator-touch-editor .annotator-touch-widget-inner { + width: 100%; + max-width: auto; + margin: 0; + border: 0; + } + + .annotator-touch-editor .annotator-controls { + border-bottom: 1px solid #D4D4D4; + } + + .annotator-touch-editor .annotator-touch-widget, + .annotator-touch-editor .annotator-touch-widget-inner, + .annotator-touch-editor .annotator-touch-widget .annotator-item:first-child textarea, + .annotator-touch-editor .annotator-controls { + border-radius: 0; + } +} diff --git a/src/plugin/touch/touch.coffee b/src/plugin/touch/touch.coffee new file mode 100644 index 000000000..74e4401de --- /dev/null +++ b/src/plugin/touch/touch.coffee @@ -0,0 +1,417 @@ +# Plugin for the Annotator to improve the experience on touch devices. In +# general it wraps the Viewer and Editor elements and increases the hit area +# of buttons. Getting the selected text is handled by polling the +# getSelection() method on the window object. This is supported by most +# devices that implement native text selection tools such as Safari on iOS. +# +# Examples +# +# jQuery("#annotator").annotator().annotator('addPlugin', 'Touch'); +# +# Returns a new instance of the Touch plugin. +class Annotator.Plugin.Touch extends Annotator.Plugin + # Export some useful globals into the class scope. + _t = Annotator._t + jQuery = Annotator.$ + + # States for the "data-state" property on the annotator-touch-controls + # element. ON means the annotattor is enabled. OFF is disabled. + @states: ON: "on", OFF: "off" + + # Template for the Touch annotator controls. + template: """ + + """ + + # Classes to be used to control the state. + classes: + hide: "annotator-touch-hide" + + # Instance options can be used to configure the annotator at runtime. + options: + # Forces the touch controls to be loaded into the page. This is useful + # for testing or if the annotator will always be used in a touch device + # (say when bundled into an application). + force: false + + # For devices that do not have support for accessing the browsers selected + # text this plugin supports the inclusion of the Highlighter library that + # goes someway to implementing these features in JavaScript. + useHighlighter: false + + # Initialises the plugin and sets up instance variables. + # + # element - The root Annotator element. + # options - An object of options for the plugin see @options. + # force: Should force plugin on desktop (default: false). + # useHighlighter: Should use Highlighter (default: false). + # + # Returns nothing. + constructor: (element, options) -> + super + + @utils = Annotator.Plugin.Touch.utils + @selection = null + @document = jQuery(document) + + # Internal: Updates the plugin after the Annotator has been loaded and + # attached to the plugin instance. This should be used to register + # Editor and Viewer fields. + # + # Returns nothing. + pluginInit: -> + return unless Annotator.supported() and (@options.force or Touch.isTouchDevice()) + + @_setupControls() + + # Only need this for some Android browsers at the moment. The simulator + # fails to select the highlights but the Galaxy Tab running 3.2 works + # okay. There is no way to feature detect whether or not the Highlighter + # should be used so it must be enabled with @options.useHighlighter. + if @options.useHighlighter + @showControls() + @highlighter = new Highlighter + root: @element[0] + prefix: "annotator-selection" + enable: false + highlightStyles: true + + # Bind tap event listeners to the highlight elements. We delegate to the + # document rather than the container to prevent WebKit requiring a + # double tap to bring up the text selection tool. + @document.delegate(".annotator-hl", "tap", preventDefault: false, @_onHighlightTap) + + @subscribe("selection", @_onSelection) + + @_unbindAnnotatorEvents() + @_setupAnnotatorEvents() + @_watchForSelection() + + # Internal: Method for tearing down a plugin, removing all event listeners + # and timers etc that it has created. This should be called when the plugin + # is removed from the DOM. + # + # Examples + # + # annotator.element.remove() + # touch.pluginDestroy() + # + # Returns nothing. + pluginDestroy: -> + @controls.remove() if @controls + @highlighter.disable() if @highlighter + @annotator.editor.unsubscribe "hide", @_watchForSelection if @annotator + + # Public: Enables the highlighter and the annotator button. This is only + # used when the highlighter is used to switch between JavaScript and + # Native text selection. + # + # Examples + # + # touch.startAnnotating() + # + # Returns itself. + startAnnotating: -> + @highlighter.enable() if @highlighter + @toggle.attr("data-state", Touch.states.ON) + @toggle.html("Stop Annotating") + this + + # Public: Disables the highlighter and the annotator button. + # + # Examples + # + # touch.startAnnotating() + # + # Returns itself. + stopAnnotating: -> + @highlighter.disable() if @highlighter + @toggle.attr("data-state", Touch.states.OFF) + @toggle.html("Start Annotating") + this + + # Public: Checks to see if the annotator is currently enabled. + # + # Examples + # + # if touch.isAnnotating() then doSomething() + # + # Returns true if the annotator is enabled. + isAnnotating: -> + usingHighlighter = @options.useHighlighter + not usingHighlighter or @toggle.attr("data-state") is Touch.states.ON + + # Public: Shows the Editor and hides the Touch controls. + # + # annotation - An annotation object to load into the Editor. + # + # Returns itself. + showEditor: (annotation) -> + @annotator.showEditor(annotation, {}) + @hideControls() + this + + # Public: Displays the touch controls. + # + # Returns itself. + showControls: -> + @controls.removeClass(@classes.hide) + this + + # Public: Hides the touch controls. + # + # Returns itself. + hideControls: -> + @controls.addClass(@classes.hide) unless @options.useHighlighter + this + + # Sets up the touch controls and binds events, also removes the default + # adder. Should only be called in the @pluginInit() method. + # + # Returns nothing. + _setupControls: -> + @annotator.adder.remove() + + @controls = jQuery(@template).appendTo("body") + + @adder = @controls.find(".annotator-add") + @adder.bind("tap", (onTapDown: (event) -> event.stopPropagation()), @_onAdderTap) + + @toggle = @controls.find(".annotator-touch-toggle") + @toggle.bind("tap": @_onToggleTap) + @toggle.hide() unless @options.useHighlighter + + # Setup method that creates the @editor and @viewer properties. Should + # only be called once by the @pluginInit() method. + # + # Returns nothing. + _setupAnnotatorEvents: -> + # Wrap the interface elements with touch controls. + @editor = new Touch.Editor(@annotator.editor) + @viewer = new Touch.Viewer(@annotator.viewer) + + # Ensure the annotate buttom is hidden when the interface is visible. + @annotator.editor.on "show", => + @_clearWatchForSelection() + @annotator.onAdderMousedown() + @highlighter.disable() if @highlighter + + @annotator.viewer.on "show", => + @highlighter.disable() if @highlighter + + @annotator.editor.on "hide", => + @utils.nextTick => + @highlighter.enable().deselect() if @highlighter + @_watchForSelection() + + @annotator.viewer.on "hide", => + @utils.nextTick => + @highlighter.enable().deselect() if @highlighter + + # Removes the default mouse event bindings created by the Annotator. + # + # Returns nothing. + _unbindAnnotatorEvents: -> + # Remove mouse events from document. + @document.unbind + "mouseup": @annotator.checkForEndSelection + "mousedown": @annotator.checkForStartSelection + + # Unbind mouse events from the root element to prevent the iPad giving + # it a grey selected outline when interacted with. + # NOTE: This currently unbinds _all_ events event those set up by + # other plugins. + @element.unbind("click mousedown mouseover mouseout") + + # Begins a timer stored in @timer that polls the page to see if a selection + # has been made. Clear the timer with @_clearWatchForSelection(). + # + # Examples + # + # jQuery(window).focus(touch._watchForSelection) + # + # Returns nothing. + _watchForSelection: => + return if @timer + + # There are occsions where Android will clear the text selection before + # firing touch events. So we slow down the polling to ensure that touch + # events get time to read the current selection. + interval = if Touch.isAndroid() then 300 else 1000 / 60 + start = new Date().getTime() + + # Use request animation frame despite the fact it runs to regularly to + # take advantage of the fact it stops running when the window is idle. + # If this becomes a performance bottleneck consider switching to a + # longer setTimeout() and managing the start/stop manually. + step = => + progress = (new Date().getTime()) - start + if progress > interval + start = new Date().getTime() + @_checkSelection() + @timer = @utils.requestAnimationFrame.call(window, step) + step() + + # Clears the @timer that polls for selections in the document. Call this + # when the user is idle or selection is not required. + # + # Returns nothing. + _clearWatchForSelection: -> + @utils.cancelAnimationFrame.call(window, @timer) + @timer = null + + # Checks the current text selection and if changed fires the "selection" + # event with the currently selected Range object and the plugin instance + # passed in as an argument. + # + # Returns nothing. + _checkSelection: -> + selection = window.getSelection() + previous = @selectionString + string = jQuery.trim(selection + "") + + if selection.rangeCount and string isnt @selectionString + @range = selection.getRangeAt(0) + @selectionString = string + + if selection.rangeCount is 0 or (@range and @range.collapsed) + @range = null + @selectionString = "" + + @publish("selection", [@range, this]) unless @selectionString is previous + + # Determines whether or not to show the annotator button depending on the + # current text selection. + # + # Examples + # + # plugin.subscribe("selection", @_onSelection) + # + # Returns nothing. + _onSelection: => + if @isAnnotating() and @range and @_isValidSelection(@range) + @adder.removeAttr("disabled") + @showControls() + else + @adder.attr("disabled", "") + @hideControls() + + # Checks to see if any part of the provided Range object falls within the + # annotator element. + # + # range - A native Range instance. + # + # Examples + # + # range = window.getSelectedText().rangeAt(0) + # if touch._isValidSelection(range) then annotateText() + # + # Returns true if the annotator element contains selected nodes. + _isValidSelection: (range) -> + # jQuery.contains() doesn't appear to work with range nodes. + inElement = (node) -> jQuery(node).parents('.annotator-wrapper').length + + isStartOffsetValid = range.startOffset < range.startContainer.length + isValidStart = isStartOffsetValid and inElement(range.startContainer) + isValidEnd = range.endOffset > 0 and inElement(range.endContainer) + + isValidStart or isValidEnd + + # Event callback for the Annotator Start/Stop button. + # + # event - A jQuery.Event touch event object. + # + # Returns nohting. + _onToggleTap: (event) => + event.preventDefault() + if @isAnnotating() then @stopAnnotating() else @startAnnotating() + + # Event callback for the Annotate adder button. Checks the current selection + # and displays the editor. + # + # event - A jQuery.Event touch event object. + # + # Returns nothing. + _onAdderTap: (event) => + event.preventDefault() + if @range + browserRange = new Annotator.Range.BrowserRange(@range) + range = browserRange.normalize().limit(@element[0]) + + if range and not @annotator.isAnnotator(range.commonAncestor) + # Here we manually apply our captured range to the annotation object + # because we cannot rely on @selectedRanges on touch browsers. + onAnnotationCreated = (annotation) => + @annotator.unsubscribe('beforeAnnotationCreated', onAnnotationCreated) + annotation.quote= range.toString() + annotation.ranges = [range] + + @annotator.subscribe('beforeAnnotationCreated', onAnnotationCreated) + + # Trigger the main adder handler which handles displaying the editor + # and triggering the correct events for persistance. + @annotator.onAdderClick(event) + + # Event callback for tap events on highlights and displays the Viewer. + # Allows events on anchor elements and those with the + # "data-annotator-clickable" attribute to pass through. Watches the + # document for further taps in order to remove the viewer. + # + # event - A jQuery.Event touch event object. + # + # Returns nothing. + _onHighlightTap: (event) => + # Check to see if clicked element should be ignored. + clickable = jQuery(event.currentTarget).parents().filter -> + jQuery(this).is('a, [data-annotator-clickable]') + return if clickable.length + + if jQuery.contains(@element[0], event.currentTarget) + original = event.originalEvent + if original and original.touches + event.pageX = original.touches[0].pageX + event.pageY = original.touches[0].pageY + + @annotator.viewer.hide() if @annotator.viewer.isShown() + @annotator.onHighlightMouseover(event) + + @document.unbind("tap", @_onDocumentTap) + @document.bind("tap", preventDefault: false, @_onDocumentTap) + + # Event handler for document taps. This is used to hide the viewer when + # the document it tapped. + # + # event - A jQuery.Event touch event object. + # + # Returns nothing. + _onDocumentTap: (event) => + unless @annotator.isAnnotator(event.target) + @annotator.viewer.hide() + @document.unbind("tap", @_onDocumentTap) unless @annotator.viewer.isShown() + + # Public: Checks to see if the current device is capable of handling + # touch events. + # + # Examples + # + # if Touch.isTouchDevice() + # # Browser handles touch events. + # else + # # Browser does not handle touch events. + # + # Returns true if the device appears so support touch events. + @isTouchDevice: -> + ('ontouchstart' of window) or window.DocumentTouch and document instanceof DocumentTouch + + # Public: Horrible browser sniffing hack for detecting Android, this should + # only be used to fix bugs in the browser where feature detection cannot + # be used. + # + # Returns true if the browser's user agent contains the string "Android". + @isAndroid: -> + (/Android/i).test(window.navigator.userAgent) diff --git a/src/plugin/touch/touch_editor.coffee b/src/plugin/touch/touch_editor.coffee new file mode 100644 index 000000000..de6afe66c --- /dev/null +++ b/src/plugin/touch/touch_editor.coffee @@ -0,0 +1,177 @@ +# Wrapper around the Annotator.Editor class. Augments the interface with +# tap friendly buttons and touch event handlers. Rather than creating a new +# class or extending the Annotator.Editor class we use the wrapper to +# change the current interface without having to heavily monkey patch the +# Annotator core. +class Annotator.Plugin.Touch.Editor extends Annotator.Delegator + # Export local globals. These are only available within the class closure. + _t = Annotator._t + jQuery = Annotator.$ + Touch = Annotator.Plugin.Touch + + # DOM event handlers and event subscriptions. + events: + # Use click for the overlay rather than tap to allow scrolling. + "click": "_onOverlayTap" + ".annotator-save tap": "_onSubmit" + ".annotator-cancel tap": "_onCancel" + ".annotator-quote-toggle tap": "_onExpandTap" + + # Classes for managing the state of the application. + classes: + expand: "annotator-touch-expand" + + # General templates. + templates: + quote: """ + + + """ + + # Sets up a new instance of the editor wrapper and augments the @editor + # element with the new interface elements. + # + # editor - An instance of Annotator.Editor. + # options - An object of options. + # + # Returns nothing. + constructor: (@editor, options) -> + super @editor.element[0], options + @element.addClass("annotator-touch-editor") + @element.wrapInner('
') + @element.find("form").addClass("annotator-touch-widget-inner") + @element.find(".annotator-controls a").addClass("annotator-button") + + # Remove the "return to submit" listener. + @element.undelegate("textarea", "keydown") + @on "hide", => @element.find(":focus").blur() + + @_setupQuoteField() + @_setupAndroidRedrawHack() + + # Expands the quote field to display more than one line. + # + # Examples + # + # editor.showQuote() + # + # Returns itself. + showQuote: -> + @quote.addClass(@classes.expand) + @quote.find("button").text _t("Collapse") + this + + # Collapses the quote field to display only one line. + # + # Examples + # + # editor.hideQuote() + # + # Returns itself. + hideQuote: -> + @quote.removeClass(@classes.expand) + @quote.find("button").text _t("Expand") + this + + # Public: Checks to see if the quote is expanded/collapsed. + # + # Returns true if the quote is collapsed. + isQuoteHidden: -> + not @quote.hasClass(@classes.expand) + + # Adds the @quote field to the @editor. Should only be called once in the + # constructor. + # + # Returns nothing. + _setupQuoteField: -> + @quote = jQuery @editor.addField + id: 'quote' + load: (field, annotation) => + @hideQuote() + @quote.find('span').html Annotator.Util.escape(annotation.quote || '') + @quote.find("button").toggle(@_isTruncated()) + + @quote.empty().addClass("annotator-item-quote") + @quote.append(@templates.quote) + + # Sets up a very spcific hack for android to redraw the view when the + # editor is displayed. The Android browser overlays it's own text box + # on to of the editor when focused, however this does not scroll with the + # rest of the UI. So to trigger this we slighly change the size of the + # focused input on scroll so the box is redrawn. + # + # This was tested on a Galaxy Tab running 3.2, hopeully this will be + # resolved in a future release. + # + # Returns nothing. + _setupAndroidRedrawHack: -> + if Touch.isAndroid() + timer = null + check = => timer = null; @_triggerAndroidRedraw() + jQuery(window).bind "scroll", -> + timer = setTimeout(check, 100) unless timer + + # Forces the Android browser to redraw it's custom text input that it + # overlays on top of the webkit fields. See @_setupAndroidRedrawHack() + # for details. + # + # Returns nothing. + _triggerAndroidRedraw: => + @_input = @element.find(":input:first") unless @_input + @_default = parseFloat(@_input.css "padding-top") unless @_default + @_multiplier = (@_multiplier or 1) * -1 + @_input[0].style.paddingTop = (@_default + @_multiplier) + "px" + @_input[0].style.paddingTop = (@_default - @_multiplier) + "px" + + # Determines if the quoted text is larger than the containing element + # when collapsed. This can be used to display the expand/collapse button. + # + # Returns true if the text is larger than the containing element. + _isTruncated: -> + isHidden = @isQuoteHidden() + + @hideQuote() unless isHidden + truncatedHeight = @quote.height() + @showQuote() + expandedHeight = @quote.height() + + # Restore previous state. + if isHidden then @hideQuote() else @showQuote() + + return expandedHeight > truncatedHeight + + # Event handler for the expand button in the quote field. + # + # event - A jQuery.Event tap event object. + # + # Returns nothing. + _onExpandTap: (event) => + event.preventDefault() + event.stopPropagation() + if @isQuoteHidden() then @showQuote() else @hideQuote() + + # Event handler for the submit button in the editor. + # + # event - A jQuery.Event tap event object. + # + # Returns nothing. + _onSubmit: (event) => + event.preventDefault() + @editor.submit() + + # Event handler for the cancel button in the editor. + # + # event - A jQuery.Event tap event object. + # + # Returns nothing. + _onCancel: (event) => + event.preventDefault() + @editor.hide() + + # Event handler for the overlay. + # + # event - A jQuery.Event click event object. + # + # Returns nothing. + _onOverlayTap: (event) => + @editor.hide() if event.target is @element[0] diff --git a/src/plugin/touch/touch_utils.coffee b/src/plugin/touch/touch_utils.coffee new file mode 100644 index 000000000..82f756089 --- /dev/null +++ b/src/plugin/touch/touch_utils.coffee @@ -0,0 +1,131 @@ +# Adds a new "tap" event to jQuery. This offers improved performance over +# click for touch devices whcih often have up to a 300ms delay before +# triggering callbacks. Instead it uses a combination of touchstart and +# touchend events to to create a fake click. It will also cancel the event +# after 300ms (to allow the user to perform a "longtap") or if the touchend +# event is triggered on a different element. +# +# Additonal options can be provided as part of the eventData object. +# +# preventDefault - If false will not call preventDefault() on the touchstart +# event (deafult: true). +# onTapDown - Callback for the "touchstart" incase additonal code needs +# to be run such as event.stopPropagation(). +# onTapUp - Callabck for the "touchend" event, called after the main +# event handler. +# timeout - Time to allow before cancelling the event (default: 300). +# +# Example +# +# jQuery("a").bind "tap", => +# # This is called on "touchend" on the same element. +# +# options = +# preventDefault: false +# onTapDown: (event) -> event.stopPropagation() +# jQuery(doument).delegate "button", "tap", options, => +# # This is called on "touchend" on the same element. +jQuery.event.special.tap = + add: (eventHandler) -> + data = eventHandler.data = eventHandler.data or {} + context = this + + onTapStart = (event) -> + event.preventDefault() unless data.preventDefault is false + data.onTapDown.apply(this, arguments) if data.onTapDown + + data.event = event + data.touched = setTimeout -> + data.touched = null + , data.timeout or 300 + jQuery(document).bind(touchend: onTapEnd, mouseup: onTapEnd) + + onTapEnd = (event) -> + if data.touched? + clearTimeout(data.touched) + if event.target is context or jQuery.contains(context, event.target) + handler = eventHandler.origHandler or eventHandler.handler + handler.call(this, data.event) + data.touched = null + + data.onTapUp.apply(this, arguments) if data.onTapUp + + jQuery(document).unbind(touchstart: onTapEnd, mousedown: onTapEnd) + + data.tapHandlers = touchstart: onTapStart, mousedown: onTapStart + if eventHandler.selector + jQuery(context).delegate(eventHandler.selector, data.tapHandlers) + else + jQuery(context).bind(data.tapHandlers) + + remove: (eventHandler) -> + jQuery(this).unbind(eventHandler.data.tapHandlers) + +# Add support for "touch" events. +Annotator.Delegator.natives.push("touchstart", "touchmove", "touchend", "tap") + +Annotator.Plugin.Touch.utils = do -> + # Pinched from Paul Irish's blog. + # See: http://paulirish.com/2011/requestanimationframe-for-smart-animating/ + vendors = ['ms', 'moz', 'webkit', 'o'] + + requestAnimationFrame = window.requestAnimationFrame + cancelAnimationFrame = window.cancelAnimationFrame + + for prefix in vendors when !requestAnimationFrame + requestAnimationFrame = window["#{prefix}RequestAnimationFrame"] + cancelAnimationFrame = window["#{prefix}CancelAnimationFrame"] or + window["#{prefix}CancelRequestAnimationFrame"] + + unless requestAnimationFrame + lastTime = 0 + requestAnimationFrame = (callback, element) -> + currTime = new Date().getTime() + timeToCall = Math.max(0, 16 - (currTime - lastTime)) + lastTime = currTime + timeToCall + window.setTimeout((-> callback(currTime + timeToCall)), timeToCall) + + unless cancelAnimationFrame + cancelAnimationFrame = (id) -> clearTimeout(id) + + { + # Public: Cross browser compatibile version of requestAnimationFrame(). + # + # callback - A function to be called when the next frame is available. + # + # Examples + # + # var id = utils.requestAnimationFrame -> + # doSomethingCool() + # + # Returns a id to cancel the request. + requestAnimationFrame: requestAnimationFrame + + # Public: Cross browser compatibile version of cancelAnimationFrame(). + # + # id - A request id. + # + # Examples + # + # id = utils.requestAnimationFrame -> + # thisWillNeverBeCalled() + # utils.cancelAnimationFrame(id) + # + # Returns nothing. + cancelAnimationFrame: cancelAnimationFrame + + # Public: Defer a callback until the next available moment. This is useful + # for queuing a function to run in the near future for example to run a + # function after the current callback stack has run. + # + # fn - A function to defer. + # + # Examples + # + # annotator.editor.on "show", -> + # # Hide viewer after rest of "show" events have fired. + # utils.nextTick(annotator.viewer.show) + # + # Returns nothing. + nextTick: (fn) -> setTimeout(fn, 0) + } diff --git a/src/plugin/touch/touch_viewer.coffee b/src/plugin/touch/touch_viewer.coffee new file mode 100644 index 000000000..e18cecde0 --- /dev/null +++ b/src/plugin/touch/touch_viewer.coffee @@ -0,0 +1,77 @@ +# Wrapper around the Annotator.Viewer class. Augments the interface with +# tap friendly buttons and touch event handlers. Rather than creating a new +# class or extending the Annotator.Viewer class we use the wrapper to +# change the current interface without having to heavily monkey patch the +# Annotator core. +class Annotator.Plugin.Touch.Viewer extends Annotator.Delegator + jQuery = Annotator.$ + + # Events bound to the element. + events: + ".annotator-item tap": "_onTap" + ".annotator-edit tap": "_onEdit" + ".annotator-delete tap": "_onDelete" + + # Sets up the wrapper and instance methods. + # + # viewer - An instance of Annotator.Viewer. + # options - An object of instance options. + # + # Returns nothing. + constructor: (@viewer, options) -> + super @viewer.element[0], options + + @element.unbind("click") + @element.addClass("annotator-touch-widget annotator-touch-viewer") + + @on("load", @_onLoad) + + # Public: Hides edit controls for all displayed annotations. + # + # Examples + # + # jQuery(document).click -> + # viewer.hideAllControls() + # + # Returns itself. + hideAllControls: -> + @element.find(".annotator-item").removeClass(@viewer.classes.showControls) + this + + # Event handler called when a field is loaded. Augments the field with + # additonal classes and event handlers. + # + # Returns nothing. + _onLoad: => + controls = @element.find(".annotator-controls") + controls.toggleClass("annotator-controls annotator-touch-controls") + controls.find("button").addClass("annotator-button") + + # Callback event called when a field is tapped. + # + # event - A jQuery.Event touchend event. + # + # Returns nothing. + _onTap: (event) -> + target = jQuery(event.currentTarget) + isVisible = target.hasClass(@viewer.classes.showControls) + @hideAllControls() + target.addClass(@viewer.classes.showControls) unless isVisible + + # Callback event called when an edit button is tapped. + # + # event - A jQuery.Event touchend event. + # + # Returns nothing. + _onEdit: (event) -> + event.preventDefault() + @viewer.onEditClick(event) + + # Callback event called when an delete button is tapped. + # + # event - A jQuery.Event touchend event. + # + # Returns nothing. + _onDelete: (event) -> + event.preventDefault() + @viewer.onDeleteClick(event) From d37d7b4b873807c29760cbd3f01ee1bc9de751ea Mon Sep 17 00:00:00 2001 From: wangcongowen Date: Sat, 4 Apr 2020 17:52:45 -0400 Subject: [PATCH 03/12] Added Plugin Filter --- demo.html | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/demo.html b/demo.html index 8390ce871..4afe70d2b 100644 --- a/demo.html +++ b/demo.html @@ -35,6 +35,9 @@ + + + @@ -94,6 +97,26 @@

Header Level 3

.annotator('addPlugin', 'Permissions') .annotator('addPlugin', 'Markdown') .annotator('addPlugin', 'Tags') + .annotator('addPlugin', 'Filter', { + filters: [ + { + label: 'Tag', + property: 'tags', + isFiltered: function (input, tags) { + if (input && tags && tags.length) { + var keywords = input.split(/\s+/g); + for (var i = 0; i < keywords.length; i += 1) { + for (var j = 0; j < tags.length; j += 1) { + if (tags[j].indexOf(keywords[i]) !== -1) { + return true; + } + } + } + } + return false; + }} + ] + }) .annotator('addPlugin', 'Touch', { force: location.search.indexOf('force') > -1, useHighlighter: location.search.indexOf('highlighter') > -1 From e54137d000981ef11048901530bb6e4b6a9680f7 Mon Sep 17 00:00:00 2001 From: wangcongowen Date: Sat, 4 Apr 2020 21:32:35 -0400 Subject: [PATCH 04/12] Added Plugin Elasticsearch --- demo.html | 22 +- pkg/Makefile | 22 +- src/plugin/{touch => }/annotator.touch.css | 0 src/plugin/elasticsearch.coffee | 338 +++++++++++++++++++++ src/plugin/elasticsearch_store.coffee | 177 +++++++++++ src/plugin/{touch => }/touch.coffee | 0 src/plugin/{touch => }/touch_editor.coffee | 0 src/plugin/{touch => }/touch_utils.coffee | 0 src/plugin/{touch => }/touch_viewer.coffee | 0 tools/preamble | 5 +- 10 files changed, 548 insertions(+), 16 deletions(-) rename src/plugin/{touch => }/annotator.touch.css (100%) create mode 100644 src/plugin/elasticsearch.coffee create mode 100644 src/plugin/elasticsearch_store.coffee rename src/plugin/{touch => }/touch.coffee (100%) rename src/plugin/{touch => }/touch_editor.coffee (100%) rename src/plugin/{touch => }/touch_utils.coffee (100%) rename src/plugin/{touch => }/touch_viewer.coffee (100%) diff --git a/demo.html b/demo.html index 4afe70d2b..53bd1ab31 100644 --- a/demo.html +++ b/demo.html @@ -49,6 +49,10 @@ + + + + @@ -56,6 +60,8 @@

Javascript annotation service test

+

Current Connectivity:

+

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.

@@ -120,9 +126,19 @@

Header Level 3

.annotator('addPlugin', 'Touch', { force: location.search.indexOf('force') > -1, useHighlighter: location.search.indexOf('highlighter') > -1 - }); - - $('#airlock').data('annotator').plugins['Permissions'].setUser("Joe Bloggs"); + }) + .annotator('addPlugin', 'Elasticsearch', { + online: function() { + return jQuery("#status").text("Online"); + }, + offline: function() { + return jQuery("#status").text("Offline"); + }, + url: "http://localhost:9200", + index: "annotation" + }); + + //$('#airlock').data('annotator').plugins['Permissions'].setUser("Joe Bloggs"); } }); diff --git a/pkg/Makefile b/pkg/Makefile index 8cf119447..10355e85a 100644 --- a/pkg/Makefile +++ b/pkg/Makefile @@ -26,13 +26,15 @@ PLUGINS=\ plugin/store.coffee \ plugin/tags.coffee \ plugin/unsupported.coffee \ - plugin/touch/touch.coffee \ - plugin/touch/touch_editor.coffee \ - plugin/touch/touch_utils.coffee \ - plugin/touch/touch_viewer.coffee + plugin/touch.coffee \ + plugin/touch_editor.coffee \ + plugin/touch_utils.coffee \ + plugin/touch_viewer.coffee \ + plugin/elasticsearch.coffee \ + plugin/elasticsearch_store.coffee PLUGINS_RESOURCES=\ - plugin/touch/annotator.touch.css + plugin/annotator.touch.css ANNOTATOR_FULL=\ $(ANNOTATOR) \ @@ -45,10 +47,12 @@ ANNOTATOR_FULL=\ plugin/markdown.coffee \ plugin/tags.coffee \ plugin/kitchensink.coffee \ - plugin/touch/touch.coffee \ - plugin/touch/touch_editor.coffee \ - plugin/touch/touch_utils.coffee \ - plugin/touch/touch_viewer.coffee + plugin/touch.coffee \ + plugin/touch_editor.coffee \ + plugin/touch_utils.coffee \ + plugin/touch_viewer.coffee \ + plugin/elasticsearch.coffee \ + plugin/elasticsearch_store.coffee BOOKMARKLET=\ $(ANNOTATOR) \ diff --git a/src/plugin/touch/annotator.touch.css b/src/plugin/annotator.touch.css similarity index 100% rename from src/plugin/touch/annotator.touch.css rename to src/plugin/annotator.touch.css diff --git a/src/plugin/elasticsearch.coffee b/src/plugin/elasticsearch.coffee new file mode 100644 index 000000000..f9c015332 --- /dev/null +++ b/src/plugin/elasticsearch.coffee @@ -0,0 +1,338 @@ +# Annotator plugin that handles storing annotations locally. It also detects +# the browsers connectivity allowing you to sync annotations with an external +# persistant store. +# +# As well as the online() and offline() callbacks that can be provided when +# the plugin is initialised "online" and "offline" events are also triggered. +# +# Also triggered are the "beforeAnnotationLoaded" and "annotationLoaded" +# events. These are fired when the annotions are extracted from localStorage. +# "beforeAnnotationLoaded" should always be used to modify the annotation and +# "annotationLoaded" for anything that needs to happen afterward. +# +# Examples +# +# annotator 'addPlugin', 'Offline', +# online: (plugin) -> +# startServerPoll() +# offline: (plugin) -> +# cancelServerPoll() +# +# Returns a new instance of the Elasticsearch plugin. +Annotator.Plugin.Elasticsearch = class Elasticsearch extends Annotator.Plugin + # Export Annotator properties into the local scope. + _t = Annotator._t + jQuery = Annotator.$ + + # Prefix for all annotation keys assigned to the store. + @ANNOTATION_PREFIX = "annotation_" + + # Public: Creates a reasonably unique identifier based on the current time + # and a randomly generated value. This is really only suitable for local + # deployments, if you're going to be using these ids to persist annotations + # elsewhere it would be worth assigning a RFC4122 compatible uuid using the + # setAnnotationData() option. + # + # Examples + # + # Elasticsearch.uuid() #=> "92992580798454581328033163230" + # + # Returns a randomly generated string. + @uuid = -> ("" + Math.random() + new Date().getTime()).slice(2) + + # Default event listeners. + events: + "annotationCreated": "_onAnnotationCreated" + "annotationUpdated": "_onAnnotationUpdated" + "annotationDeleted": "_onAnnotationDeleted" + + # Default options for the plugin. + options: + # Creates a unique key for the annotation to be stored against. This uses + # the annotations "id" property if it has one, otherwise it will assign it + # a randomly generated key. + # + # annotation - An annotation object. + # + # Examples + # + # annotation = {id: "a-unique-id"} + # @getUniqueKey(annotation) #=> "a-unique-id" + # + # Returns a unique identifier for the annotation. + getUniqueKey: (annotation) -> + annotation.id = Elasticsearch.uuid() unless annotation.id + annotation.id + + # Checks to see if the annotation should be loaded into this page. If + # the function returns true then it will be loaded. By default it will + # always return true. This can be overrided in the options. + # + # annotation - An annotation object. + # + # Examples + # + # @shouldLoadAnnotation(annotation) #=> true + # + # Returns true or false. + shouldLoadAnnotation: (annotation) -> true + + # Creates a new instance of the plugin and initialises instance variables. + # + # element - The root annotator element. + # options - An object literal of options. + # online: Function that is called when the plugin goes + # online. Recieves the plugin object as an + # argument. + # offline: Function that is called when the plugin goes + # offline. Recieves the plugin object as an + # argument. + # getUniqueKey: Function that accepts an annotation to return + # a unique value. By default it returns the id. + # setAnnotationData: Accepts a newly created annotation for + # modification such as adding properties. + # shouldLoadAnnotation: Function that should return if the + # annotation should be loaded in this page. + # + # Returns nothing. + constructor: (elements,options) -> + super + @url = options.url + @index = options.index + + @store = new Elasticsearch.Store(@url, @index) + @cache = {} + handlers = + online: "online" + offline: "offline" + beforeAnnotationLoaded: "setAnnotationData" + beforeAnnotationCreated: "setAnnotationData" + + for own event, handler of handlers + if typeof @options[handler] is "function" + @on(event, jQuery.proxy @options, handler) + + # Internal: Initialises the plugin, called by the Annotator object once a + # new instance of the object has been created and the @annotator property + # attached. + # + # Returns nothing. + pluginInit: -> + return unless Annotator.supported() + + @loadAnnotationsFromStore() + if @isOnline() then @online() else @offline() + jQuery(window).bind(online: @_onOnline, offline: @_onOffline) + + # Public: Returns an object of loaded annotations indexed by unique key. + # + # Examples + # + # plugin.annotations() #=> {1: {id: 1, text: "Test"}, 2: {id: 2, ...}} + # + # Returns an object. + annotations: -> @cache + + # Public: Publishes the "online" event on the plugin. All registered + # subscribers recieve the plugin instance as the first argument. + # + # Examples + # + # plugin.on "online", -> alert("We're now online!") + # plugin.online() # Alert box is displayed. + # + # Returns itself. + online: -> + @publish "online", [this] + this + + # Public: Publishes the "offline" event on the plugin. All registered + # subscribers recieve the plugin instance as the first argument. + # + # Examples + # + # plugin.on "offline", -> alert("We're now offline!") + # plugin.offline() # Alert box is displayed. + # + # Returns itself. + offline: -> + @publish "offline", [this] + this + + # Public: Checks to see if the browser currently has a network connection. + # + # Examples + # + # if plugin.isOnline() then backupData() + # + # Returns true if the browser has connectivitiy. + isOnline: -> window.navigator.onLine + + # Public: Loads all stored annotations into the page. This should generally + # only be called on page load. + # + # Examples + # + # offline.loadAnnotationsFromStore() + # + # Returns itself. + loadAnnotationsFromStore: -> + current = [] + annotations = @store.all(Elasticsearch.ANNOTATION_PREFIX) + for annotation in annotations when @options.shouldLoadAnnotation(annotation) + # beforeAnnotationLoaded allows the annotation data to be manipulated + # before it is loaded into Annotator. + @publish("beforeAnnotationLoaded", [annotation, this]) + @publish("annotationLoaded", [annotation, this]) + @cache[@keyForAnnotation(annotation)] = annotation + current.push(annotation) + @annotator.loadAnnotations(current) if current.length + this + + # Public: Adds an annotation to the store, also adds it to the current + # page if needed. + # + # annotation - An annotation object to save. + # options - An object of method options. + # silent: If true prevents the annotator from firing the + # "annotationCreated" event. + # + # Examples + # + # getAnnotationFromServer (ann) -> + # offline.addAnnotation(ann) + # + # Returns itself. + addAnnotation: (annotation, options={}) -> + isLoaded = @cache[@options.getUniqueKey(annotation)] + if not isLoaded and @options.shouldLoadAnnotation(annotation) + @annotator.setupAnnotation(annotation, options.silent) + else + @updateStoredAnnotation(annotation) + this + + # Public: Removes an annotation from the store, also removes it from the + # current page if needed. + # + # annotation - An annotation object to remove. + # + # Examples + # + # getAnnotationFromServer (ann) -> + # offline.addAnnotation(ann) + # + # Returns itself. + removeAnnotation: (annotation) -> + if @options.shouldLoadAnnotation(annotation) + @annotator.deleteAnnotation(annotation) + else + @removeStoredAnnotation(annotation) + this + + # Public: Updates the locally stored copy of the annotation. + # + # annotation - An annotation object. + # + # Examples + # + # onAnnotationUpdated = (ann) -> + # store.updateAnnotation(ann) + # + # Returns itself. + updateStoredAnnotation: (annotation) -> + id = @keyForAnnotation(annotation) + key = @keyForStore(annotation) + + local = @cache[id] + if local + jQuery.extend(local, annotation) + else + local = @cache[id] = annotation + + storable = jQuery.extend({}, local) + delete storable.highlights + + @store.set(key, storable) + this + + # Public: Removes the annotation from local storage. + # + # annotation - An annotation object. + # + # Examples + # + # onAnnotationDeleted = (ann) -> + # store.removeAnnotation(ann) + # + # Returns itself. + removeStoredAnnotation: (annotation) -> + id = @keyForAnnotation(annotation) + key = @keyForStore(annotation) + @store.remove(key) + delete @cache[id] + this + + # Internal: Retrieves a key for an annotation. This can be customised using + # the getUniqueKey() option. By default it will use the "id" property on the + # annotation. + # + # annotation - An annotation object. + # + # Examples + # + # key = @keyForAnnotation(annotation)= + # + # Returns a unique key for the annotation. + keyForAnnotation: (annotation) -> + @options.getUniqueKey.call(this, annotation, this) + + # Internal: Retrieves a key for the local storage. + # + # annotation - An annotation object. + # + # Examples + # + # key = @keyForStore(annotation) + # store.set(key, annotation) + # + # Returns a key to be used to store the annotation. + keyForStore: (annotation) -> + Elasticsearch.ANNOTATION_PREFIX + @keyForAnnotation(annotation) + + # Event callback for the "online" window event. + # + # event - A jQuery event object. + # + # Returns nothing. + _onOnline: (event) => @online() + + # Event callback for the "offline" window event. + # + # event - A jQuery event object. + # + # Returns nothing. + _onOffline: (event) => @offline() + + # Event callback for the "annotationCreated" event. + # + # annotation - An annotation object. + # + # Returns nothing. + _onAnnotationCreated: (annotation) -> + @updateStoredAnnotation(annotation) + + # Event callback for the "annotationUpdated" event. + # + # annotation - An annotation object. + # + # Returns nothing. + _onAnnotationUpdated: (annotation) -> + @updateStoredAnnotation(annotation) + + # Event callback for the "annotationDeleted" event. + # + # annotation - An annotation object. + # + # Returns nothing. + _onAnnotationDeleted: (annotation) -> + @removeStoredAnnotation(annotation) diff --git a/src/plugin/elasticsearch_store.coffee b/src/plugin/elasticsearch_store.coffee new file mode 100644 index 000000000..4e677e5f0 --- /dev/null +++ b/src/plugin/elasticsearch_store.coffee @@ -0,0 +1,177 @@ +# Helper methods for working with elasticsearch. Adds support for storing +# objects as serialized JSON, setting expiry times on stored keys and catching +# exceptions. +# +# Caught execeptions can be listened for by subscribing to the "error" event +# which will recieve the error object. +# +# Examples +# +# store = new Store() +# +# store.set("name", "Aron") +# store.get("name") #=> Aron +# store.remove("name") +# +# Returns a new instance of Store. +Annotator.Plugin.Elasticsearch.Store = class Store extends Annotator.Delegator + + constructor: (url, index) -> + @url = url + @index = index + + # Internal: Prefix for all keys stored by the store. + @KEY_PREFIX: "annotator_elasticsearch_" + + # Internal: Delimeter used to seperate the cache time from the value. + @CACHE_DELIMITER: "--cache--" + + # Public: Checks to see if the current browser supports local storage. + # + # Examples + # + # store = new Store if Store.isSupported() + # + # Returns true if the browser supports local storage. + @isSupported: -> + true + + # Public: Get the current time as a unix timestamp in + # milliseconds. + # + # Examples + # + # Store.now() //=> 1325099398242 + # + # Returns the current time in milliseconds. + @now: -> new Date().getTime() + + # Public: Extracts all the values stored under the KEY_PREFIX. An additional + # partial key can be provided that will be added to the prefix. + # + # partial - A partial database key (default: ""). + # + # Examples + # + # values = store.all() + # some = store.all("user") # All keys beginning with "user" + # + # Returns an array of extracted keys. + all: (partial="") -> + values = [] + $.ajax "#{@url}/#{@index}/_search?q=*:*&size=2500", + async: false + dataType:'json' + contentType: "application/json" + success : (data, status, xhr) -> + for i of data.hits.hits + values.push(data.hits.hits[i]._source) + error : (xhr, status, err) -> + console.log("error:"+err) + complete : (xhr, status) -> + console.log("completed.") + values + + # Public: Sets a value for the key provided. An optional "expires" time in + # milliseconds can be provided, the key will not be accessble via #get() after + # this time. + # + # All values will be serialized with JSON.stringify() so ensure that they + # do not have recursive properties before passing them to #set(). + # + # key - A key string to set. + # value - A value to set. + # time - Expiry time in milliseconds (default: null). + # + # Examples + # + # store.set("key", 12345) + # store.set("temporary", {user: 1}, 3000) + # store.get("temporary") #=> {user: 1} + # setTimeout -> + # store.get("temporary") #=> null + # , 3000 + # + # Returns itself. + set: (key, value, time) -> + value = JSON.stringify value + value = (Store.now() + time) + Store.CACHE_DELIMITER + value if time + try + $.ajax "#{@url}/#{@index}/_doc/#{@prefixed(key)}", + type: 'PUT' + data: value + dataType: 'json' + contentType: "application/json" + success: (response) -> + console.log "AJAX Success: #{JSON.stringify(response)}" + error: (response) -> + console.log "AJAX Error: #{JSON.stringify(response)}" + catch error + this.publish('error', [error, this]) + this + + # Public: Removes the key from the storage. + # + # key - The key to remove. + # + # Examples + # + # store.set("name", "Aron") + # store.remove("key") + # store.get("name") #=> null + # + # Returns itself. + remove: (key) -> + try + $.ajax "#{@url}/#{@index}/_doc/#{@prefixed(key)}", + type: 'DELETE' + success: (response) -> + console.log "AJAX Success: #{JSON.stringify(response)}" + error: (response) -> + console.log "AJAX Error: #{JSON.stringify(response)}" + catch error + this.publish('error', [error, this]) + this + + # Public: Removes all keys in local storage with the prefix. + # + # Examples + # + # store.clear() + # + # Returns itself. + clear: -> + this + + # Internal: Applies the KEY_PREFIX to the provided key. This is used to + # namespace keys in localStorage. + # + # key - A user provided key to prefix. + # + # Examples + # + # store.prefixed("name") #=> "annotator.readmill/name" + # + # Returns a prefixed key. + prefixed: (key) -> + Store.KEY_PREFIX + key + + # Internal: Checks the expiry period (if any) of a value extracted from + # localStorage. Returns the value if it is still valid, otherwise returns + # null. + # + # param - comment + # + # Examples + # + # store.checkCache("1325099398242--cache--\"expired\") #=> null + # store.checkCache("1325199398242--cache--\"valid\") #=> "valid" + # + # Returns extracted value or null if expired. + checkCache: (value) -> + if value.indexOf(Store.CACHE_DELIMITER) > -1 + # If the expiry time has passed then return null. + cached = value.split(Store.CACHE_DELIMITER) + value = if Store.now() > cached.shift() + then null else cached.join(Store.CACHE_DELIMITER) + value diff --git a/src/plugin/touch/touch.coffee b/src/plugin/touch.coffee similarity index 100% rename from src/plugin/touch/touch.coffee rename to src/plugin/touch.coffee diff --git a/src/plugin/touch/touch_editor.coffee b/src/plugin/touch_editor.coffee similarity index 100% rename from src/plugin/touch/touch_editor.coffee rename to src/plugin/touch_editor.coffee diff --git a/src/plugin/touch/touch_utils.coffee b/src/plugin/touch_utils.coffee similarity index 100% rename from src/plugin/touch/touch_utils.coffee rename to src/plugin/touch_utils.coffee diff --git a/src/plugin/touch/touch_viewer.coffee b/src/plugin/touch_viewer.coffee similarity index 100% rename from src/plugin/touch/touch_viewer.coffee rename to src/plugin/touch_viewer.coffee diff --git a/tools/preamble b/tools/preamble index 8f2dba0b0..433abb5bb 100755 --- a/tools/preamble +++ b/tools/preamble @@ -1,18 +1,15 @@ # Change the format of End of Line char cd "$(dirname "$0")" - DATE=$(date -u "+%Y-%m-%d %H:%M:%SZ") YEAR=$(date -u "+%Y") - # ./tools/make_release exports VERSION, so use that if available if [ -n "$VERSION" ]; then VERSION="v${VERSION}" else VERSION="v$(echo "$(grep version ../package.json | cut -d\" -f4)-dev-$(git describe --always)")" fi - # print preamble, substituting variables cat ../src/preamble.coffee | sed -e "s/{{VERSION}}/$VERSION/g" \ -e "s/{{YEAR}}/$YEAR/g" \ - -e "s/{{DATE}}/$DATE/g" + -e "s/{{DATE}}/$DATE/g" \ No newline at end of file From 917b1945b50dff33c4fecc8eee54cfa455e42e96 Mon Sep 17 00:00:00 2001 From: wangcongowen Date: Sun, 5 Apr 2020 16:46:05 -0400 Subject: [PATCH 05/12] Added Plugin RichText --- demo.html | 15 + pkg/Makefile | 11 +- pkg/plugin/richText/tinymce/langs/readme.md | 3 + pkg/plugin/richText/tinymce/license.txt | 504 ++++++++++++++++++ .../plugins/emoticons/img/smiley-cool.gif | Bin 0 -> 354 bytes .../plugins/emoticons/img/smiley-cry.gif | Bin 0 -> 329 bytes .../emoticons/img/smiley-embarassed.gif | Bin 0 -> 331 bytes .../emoticons/img/smiley-foot-in-mouth.gif | Bin 0 -> 342 bytes .../plugins/emoticons/img/smiley-frown.gif | Bin 0 -> 340 bytes .../plugins/emoticons/img/smiley-innocent.gif | Bin 0 -> 336 bytes .../plugins/emoticons/img/smiley-kiss.gif | Bin 0 -> 338 bytes .../plugins/emoticons/img/smiley-laughing.gif | Bin 0 -> 343 bytes .../emoticons/img/smiley-money-mouth.gif | Bin 0 -> 321 bytes .../plugins/emoticons/img/smiley-sealed.gif | Bin 0 -> 323 bytes .../plugins/emoticons/img/smiley-smile.gif | Bin 0 -> 344 bytes .../emoticons/img/smiley-surprised.gif | Bin 0 -> 338 bytes .../emoticons/img/smiley-tongue-out.gif | Bin 0 -> 328 bytes .../emoticons/img/smiley-undecided.gif | Bin 0 -> 337 bytes .../plugins/emoticons/img/smiley-wink.gif | Bin 0 -> 350 bytes .../plugins/emoticons/img/smiley-yell.gif | Bin 0 -> 336 bytes .../tinymce/plugins/example/dialog.html | 8 + .../tinymce/plugins/media/moxieplayer.swf | Bin 0 -> 20017 bytes .../skins/lightgray/fonts/tinymce-small.eot | Bin 0 -> 9492 bytes .../skins/lightgray/fonts/tinymce-small.svg | 63 +++ .../skins/lightgray/fonts/tinymce-small.ttf | Bin 0 -> 9304 bytes .../skins/lightgray/fonts/tinymce-small.woff | Bin 0 -> 9380 bytes .../tinymce/skins/lightgray/fonts/tinymce.eot | Bin 0 -> 14308 bytes .../tinymce/skins/lightgray/fonts/tinymce.svg | 98 ++++ .../tinymce/skins/lightgray/fonts/tinymce.ttf | Bin 0 -> 14144 bytes .../skins/lightgray/fonts/tinymce.woff | Bin 0 -> 14220 bytes .../tinymce/skins/lightgray/img/anchor.gif | Bin 0 -> 53 bytes .../tinymce/skins/lightgray/img/loader.gif | Bin 0 -> 2608 bytes .../tinymce/skins/lightgray/img/object.gif | Bin 0 -> 152 bytes .../tinymce/skins/lightgray/img/trans.gif | Bin 0 -> 43 bytes src/plugin/richText/richText-annotator.css | 33 ++ src/plugin/richText/richText-annotator.js | 143 +++++ src/plugin/richText/tinymce/langs/readme.md | 3 + src/plugin/richText/tinymce/license.txt | 504 ++++++++++++++++++ .../tinymce/plugins/advlist/plugin.min.js | 1 + .../tinymce/plugins/anchor/plugin.min.js | 1 + .../tinymce/plugins/autolink/plugin.min.js | 1 + .../tinymce/plugins/autoresize/plugin.min.js | 1 + .../tinymce/plugins/autosave/plugin.min.js | 1 + .../tinymce/plugins/bbcode/plugin.min.js | 1 + .../tinymce/plugins/charmap/plugin.min.js | 1 + .../tinymce/plugins/code/plugin.min.js | 1 + .../tinymce/plugins/codesample/css/prism.css | 138 +++++ .../tinymce/plugins/codesample/plugin.min.js | 1 + .../tinymce/plugins/colorpicker/plugin.min.js | 1 + .../tinymce/plugins/contextmenu/plugin.min.js | 1 + .../plugins/directionality/plugin.min.js | 1 + .../plugins/emoticons/img/smiley-cool.gif | Bin 0 -> 354 bytes .../plugins/emoticons/img/smiley-cry.gif | Bin 0 -> 329 bytes .../emoticons/img/smiley-embarassed.gif | Bin 0 -> 331 bytes .../emoticons/img/smiley-foot-in-mouth.gif | Bin 0 -> 342 bytes .../plugins/emoticons/img/smiley-frown.gif | Bin 0 -> 340 bytes .../plugins/emoticons/img/smiley-innocent.gif | Bin 0 -> 336 bytes .../plugins/emoticons/img/smiley-kiss.gif | Bin 0 -> 338 bytes .../plugins/emoticons/img/smiley-laughing.gif | Bin 0 -> 343 bytes .../emoticons/img/smiley-money-mouth.gif | Bin 0 -> 321 bytes .../plugins/emoticons/img/smiley-sealed.gif | Bin 0 -> 323 bytes .../plugins/emoticons/img/smiley-smile.gif | Bin 0 -> 344 bytes .../emoticons/img/smiley-surprised.gif | Bin 0 -> 338 bytes .../emoticons/img/smiley-tongue-out.gif | Bin 0 -> 328 bytes .../emoticons/img/smiley-undecided.gif | Bin 0 -> 337 bytes .../plugins/emoticons/img/smiley-wink.gif | Bin 0 -> 350 bytes .../plugins/emoticons/img/smiley-yell.gif | Bin 0 -> 336 bytes .../tinymce/plugins/emoticons/plugin.min.js | 1 + .../tinymce/plugins/example/dialog.html | 8 + .../tinymce/plugins/example/plugin.min.js | 1 + .../plugins/example_dependency/plugin.min.js | 1 + .../tinymce/plugins/fullpage/plugin.min.js | 1 + .../tinymce/plugins/fullscreen/plugin.min.js | 1 + .../richText/tinymce/plugins/hr/plugin.min.js | 1 + .../tinymce/plugins/image/plugin.min.js | 1 + .../tinymce/plugins/imagetools/plugin.min.js | 1 + .../tinymce/plugins/importcss/plugin.min.js | 1 + .../plugins/insertdatetime/plugin.min.js | 1 + .../tinymce/plugins/layer/plugin.min.js | 1 + .../plugins/legacyoutput/plugin.min.js | 1 + .../tinymce/plugins/link/plugin.min.js | 1 + .../tinymce/plugins/lists/plugin.min.js | 1 + .../tinymce/plugins/media/moxieplayer.swf | Bin 0 -> 20017 bytes .../tinymce/plugins/media/plugin.min.js | 1 + .../tinymce/plugins/nonbreaking/plugin.min.js | 1 + .../tinymce/plugins/noneditable/plugin.min.js | 1 + .../tinymce/plugins/pagebreak/plugin.min.js | 1 + .../tinymce/plugins/paste/plugin.min.js | 1 + .../tinymce/plugins/preview/plugin.min.js | 1 + .../tinymce/plugins/print/plugin.min.js | 1 + .../tinymce/plugins/save/plugin.min.js | 1 + .../plugins/searchreplace/plugin.min.js | 1 + .../plugins/spellchecker/plugin.min.js | 1 + .../tinymce/plugins/tabfocus/plugin.min.js | 1 + .../tinymce/plugins/table/plugin.min.js | 2 + .../tinymce/plugins/template/plugin.min.js | 1 + .../tinymce/plugins/textcolor/plugin.min.js | 1 + .../tinymce/plugins/textpattern/plugin.min.js | 1 + .../plugins/visualblocks/css/visualblocks.css | 135 +++++ .../plugins/visualblocks/plugin.min.js | 1 + .../tinymce/plugins/visualchars/plugin.min.js | 1 + .../tinymce/plugins/wordcount/plugin.min.js | 1 + .../skins/lightgray/content.inline.min.css | 1 + .../tinymce/skins/lightgray/content.min.css | 1 + .../skins/lightgray/fonts/tinymce-small.eot | Bin 0 -> 9492 bytes .../skins/lightgray/fonts/tinymce-small.svg | 63 +++ .../skins/lightgray/fonts/tinymce-small.ttf | Bin 0 -> 9304 bytes .../skins/lightgray/fonts/tinymce-small.woff | Bin 0 -> 9380 bytes .../tinymce/skins/lightgray/fonts/tinymce.eot | Bin 0 -> 14308 bytes .../tinymce/skins/lightgray/fonts/tinymce.svg | 98 ++++ .../tinymce/skins/lightgray/fonts/tinymce.ttf | Bin 0 -> 14144 bytes .../skins/lightgray/fonts/tinymce.woff | Bin 0 -> 14220 bytes .../tinymce/skins/lightgray/img/anchor.gif | Bin 0 -> 53 bytes .../tinymce/skins/lightgray/img/loader.gif | Bin 0 -> 2608 bytes .../tinymce/skins/lightgray/img/object.gif | Bin 0 -> 152 bytes .../tinymce/skins/lightgray/img/trans.gif | Bin 0 -> 43 bytes .../tinymce/skins/lightgray/skin.ie7.min.css | 1 + .../tinymce/skins/lightgray/skin.min.css | 1 + .../tinymce/themes/modern/theme.min.js | 1 + src/plugin/richText/tinymce/tinymce.min.js | 13 + 120 files changed, 1888 insertions(+), 2 deletions(-) create mode 100644 pkg/plugin/richText/tinymce/langs/readme.md create mode 100644 pkg/plugin/richText/tinymce/license.txt create mode 100644 pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-cool.gif create mode 100644 pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-cry.gif create mode 100644 pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-embarassed.gif create mode 100644 pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-foot-in-mouth.gif create mode 100644 pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-frown.gif create mode 100644 pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-innocent.gif create mode 100644 pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-kiss.gif create mode 100644 pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-laughing.gif create mode 100644 pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-money-mouth.gif create mode 100644 pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-sealed.gif create mode 100644 pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-smile.gif create mode 100644 pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-surprised.gif create mode 100644 pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-tongue-out.gif create mode 100644 pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-undecided.gif create mode 100644 pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-wink.gif create mode 100644 pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-yell.gif create mode 100644 pkg/plugin/richText/tinymce/plugins/example/dialog.html create mode 100644 pkg/plugin/richText/tinymce/plugins/media/moxieplayer.swf create mode 100644 pkg/plugin/richText/tinymce/skins/lightgray/fonts/tinymce-small.eot create mode 100644 pkg/plugin/richText/tinymce/skins/lightgray/fonts/tinymce-small.svg create mode 100644 pkg/plugin/richText/tinymce/skins/lightgray/fonts/tinymce-small.ttf create mode 100644 pkg/plugin/richText/tinymce/skins/lightgray/fonts/tinymce-small.woff create mode 100644 pkg/plugin/richText/tinymce/skins/lightgray/fonts/tinymce.eot create mode 100644 pkg/plugin/richText/tinymce/skins/lightgray/fonts/tinymce.svg create mode 100644 pkg/plugin/richText/tinymce/skins/lightgray/fonts/tinymce.ttf create mode 100644 pkg/plugin/richText/tinymce/skins/lightgray/fonts/tinymce.woff create mode 100644 pkg/plugin/richText/tinymce/skins/lightgray/img/anchor.gif create mode 100644 pkg/plugin/richText/tinymce/skins/lightgray/img/loader.gif create mode 100644 pkg/plugin/richText/tinymce/skins/lightgray/img/object.gif create mode 100644 pkg/plugin/richText/tinymce/skins/lightgray/img/trans.gif create mode 100644 src/plugin/richText/richText-annotator.css create mode 100644 src/plugin/richText/richText-annotator.js create mode 100644 src/plugin/richText/tinymce/langs/readme.md create mode 100644 src/plugin/richText/tinymce/license.txt create mode 100644 src/plugin/richText/tinymce/plugins/advlist/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/anchor/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/autolink/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/autoresize/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/autosave/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/bbcode/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/charmap/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/code/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/codesample/css/prism.css create mode 100644 src/plugin/richText/tinymce/plugins/codesample/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/colorpicker/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/contextmenu/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/directionality/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/emoticons/img/smiley-cool.gif create mode 100644 src/plugin/richText/tinymce/plugins/emoticons/img/smiley-cry.gif create mode 100644 src/plugin/richText/tinymce/plugins/emoticons/img/smiley-embarassed.gif create mode 100644 src/plugin/richText/tinymce/plugins/emoticons/img/smiley-foot-in-mouth.gif create mode 100644 src/plugin/richText/tinymce/plugins/emoticons/img/smiley-frown.gif create mode 100644 src/plugin/richText/tinymce/plugins/emoticons/img/smiley-innocent.gif create mode 100644 src/plugin/richText/tinymce/plugins/emoticons/img/smiley-kiss.gif create mode 100644 src/plugin/richText/tinymce/plugins/emoticons/img/smiley-laughing.gif create mode 100644 src/plugin/richText/tinymce/plugins/emoticons/img/smiley-money-mouth.gif create mode 100644 src/plugin/richText/tinymce/plugins/emoticons/img/smiley-sealed.gif create mode 100644 src/plugin/richText/tinymce/plugins/emoticons/img/smiley-smile.gif create mode 100644 src/plugin/richText/tinymce/plugins/emoticons/img/smiley-surprised.gif create mode 100644 src/plugin/richText/tinymce/plugins/emoticons/img/smiley-tongue-out.gif create mode 100644 src/plugin/richText/tinymce/plugins/emoticons/img/smiley-undecided.gif create mode 100644 src/plugin/richText/tinymce/plugins/emoticons/img/smiley-wink.gif create mode 100644 src/plugin/richText/tinymce/plugins/emoticons/img/smiley-yell.gif create mode 100644 src/plugin/richText/tinymce/plugins/emoticons/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/example/dialog.html create mode 100644 src/plugin/richText/tinymce/plugins/example/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/example_dependency/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/fullpage/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/fullscreen/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/hr/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/image/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/imagetools/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/importcss/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/insertdatetime/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/layer/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/legacyoutput/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/link/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/lists/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/media/moxieplayer.swf create mode 100644 src/plugin/richText/tinymce/plugins/media/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/nonbreaking/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/noneditable/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/pagebreak/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/paste/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/preview/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/print/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/save/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/searchreplace/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/spellchecker/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/tabfocus/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/table/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/template/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/textcolor/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/textpattern/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/visualblocks/css/visualblocks.css create mode 100644 src/plugin/richText/tinymce/plugins/visualblocks/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/visualchars/plugin.min.js create mode 100644 src/plugin/richText/tinymce/plugins/wordcount/plugin.min.js create mode 100644 src/plugin/richText/tinymce/skins/lightgray/content.inline.min.css create mode 100644 src/plugin/richText/tinymce/skins/lightgray/content.min.css create mode 100644 src/plugin/richText/tinymce/skins/lightgray/fonts/tinymce-small.eot create mode 100644 src/plugin/richText/tinymce/skins/lightgray/fonts/tinymce-small.svg create mode 100644 src/plugin/richText/tinymce/skins/lightgray/fonts/tinymce-small.ttf create mode 100644 src/plugin/richText/tinymce/skins/lightgray/fonts/tinymce-small.woff create mode 100644 src/plugin/richText/tinymce/skins/lightgray/fonts/tinymce.eot create mode 100644 src/plugin/richText/tinymce/skins/lightgray/fonts/tinymce.svg create mode 100644 src/plugin/richText/tinymce/skins/lightgray/fonts/tinymce.ttf create mode 100644 src/plugin/richText/tinymce/skins/lightgray/fonts/tinymce.woff create mode 100644 src/plugin/richText/tinymce/skins/lightgray/img/anchor.gif create mode 100644 src/plugin/richText/tinymce/skins/lightgray/img/loader.gif create mode 100644 src/plugin/richText/tinymce/skins/lightgray/img/object.gif create mode 100644 src/plugin/richText/tinymce/skins/lightgray/img/trans.gif create mode 100644 src/plugin/richText/tinymce/skins/lightgray/skin.ie7.min.css create mode 100644 src/plugin/richText/tinymce/skins/lightgray/skin.min.css create mode 100644 src/plugin/richText/tinymce/themes/modern/theme.min.js create mode 100644 src/plugin/richText/tinymce/tinymce.min.js diff --git a/demo.html b/demo.html index 53bd1ab31..e8bba8a38 100644 --- a/demo.html +++ b/demo.html @@ -52,6 +52,11 @@ + + + + + @@ -136,6 +141,16 @@

Header Level 3

}, url: "http://localhost:9200", index: "annotation" + }) + .annotator('addPlugin','RichText',{ + tinymce:{ + selector: "li.annotator-item textarea", + plugins: "media image insertdatetime link code", + menubar: false, + toolbar_items_size: 'small', + extended_valid_elements : "iframe[src|frameborder|style|scrolling|class|width|height|name|align|id]", + toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image media rubric | code ", + } }); //$('#airlock').data('annotator').plugins['Permissions'].setUser("Joe Bloggs"); diff --git a/pkg/Makefile b/pkg/Makefile index 10355e85a..c7a80224e 100644 --- a/pkg/Makefile +++ b/pkg/Makefile @@ -36,6 +36,9 @@ PLUGINS=\ PLUGINS_RESOURCES=\ plugin/annotator.touch.css +PLUGINS_JAVASCRIPT=\ + plugin/richText + ANNOTATOR_FULL=\ $(ANNOTATOR) \ plugin/unsupported.coffee \ @@ -66,7 +69,7 @@ BOOKMARKLET=\ BOOKMARKLET_CFG=../contrib/bookmarklet/config.json BOOKMARKLET_SRC=../contrib/bookmarklet/src/bookmarklet.js -all: annotator plugins plugins-resources annotator-full bookmarklet +all: annotator plugins plugins-resources plugins_javascript annotator-full bookmarklet annotator: annotator.min.js annotator.min.css @@ -76,7 +79,11 @@ plugins: $(addprefix annotator.,$(PLUGIN_NAMES:.coffee=.min.js)) plugins-resources: @echo "Plugin resource:" ../src/$(PLUGINS_RESOURCES) @cp ../src/$(PLUGINS_RESOURCES) ../css/`echo $(PLUGINS_RESOURCES) | sed 's:.*/::'` - + +plugins_javascript: + @mkdir -p $(PLUGINS_JAVASCRIPT) + @cp -r ../src/$(PLUGINS_JAVASCRIPT) plugin + annotator-full: annotator-full.min.js _preamble.map: diff --git a/pkg/plugin/richText/tinymce/langs/readme.md b/pkg/plugin/richText/tinymce/langs/readme.md new file mode 100644 index 000000000..a52bf03f9 --- /dev/null +++ b/pkg/plugin/richText/tinymce/langs/readme.md @@ -0,0 +1,3 @@ +This is where language files should be placed. + +Please DO NOT translate these directly use this service: https://www.transifex.com/projects/p/tinymce/ diff --git a/pkg/plugin/richText/tinymce/license.txt b/pkg/plugin/richText/tinymce/license.txt new file mode 100644 index 000000000..1837b0acb --- /dev/null +++ b/pkg/plugin/richText/tinymce/license.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-cool.gif b/pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-cool.gif new file mode 100644 index 0000000000000000000000000000000000000000..ba90cc36fb0415d0273d1cd206bff63fd9c91fde GIT binary patch literal 354 zcmV-o0iFIwNk%w1VG;lm0Mr!#3ke00dJfFY%i+lrhK7V(RutUQJhPY;?(XfrsZKgL z7WLQ^zPO&zzav{)SL^9nBOw~z(=orMEH5uC-P_gr`uhCnASMa|$-iRw?m_(dUwU8) zq>Kx}s1_F$4FCWDA^8LW0018VEC2ui01^Na000Hw;3tYzX_jM3Qpv$_M?zI9i5=0S zX-{-uv=l3%&P0s%m9Ox_a(m_c|u z01g3U0`Wll5)poVdma=N8y<3f0Sf~hXmTC}2oxMW4FdxUj+z4<0}lrX2nP=qkDRIt z9Ge*(qzMrj3jrIOjvI{`5eWzt3`G_T8yChG8w(a19SkK12@M(+799Zr9n=~PzBCmA z5)BU-)YKUd4H5!D9|!^o9kWIe9SH(WDHRk92}DZ?3})2$P@$55g90f0N)ZA8JID5J Aw*UYD literal 0 HcmV?d00001 diff --git a/pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-cry.gif b/pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-cry.gif new file mode 100644 index 0000000000000000000000000000000000000000..74d897a4f6d22e814e2b054e98b8a75fb464b4be GIT binary patch literal 329 zcmV-P0k-}}Nk%w1VG;lm0Mr-&E)xPSit@9T3%;vR+|V+?t0A(pllJjXrMl7n=_A_a za^B+Su$LjvyC3@TIQZNZa##w=!k(SO^P#bO*w(eU#;{U83XFCU_V)J5wrb+;g2vkN z#>U24qVoOvY5)KLA^8LW0018VEC2ui01^Na000HX;3tY$X_jM3QUfCh%s^o(nF++< zc?Th6v=oL>*by8K!mhvwelUXuuW&&U9iGO3hM@>Njw{l^#0q9mWpcefdI;O$;efnY zkd~@r-o$*74FCWI1%d((4+jDz0va0>69^fI6%`W{8w!gU1pyL>prH>E0R<%k6Aq%H z4ij+^9TEwM5P}eh2@)L<~6+>@EpxfA0YrcPNsSu literal 0 HcmV?d00001 diff --git a/pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-embarassed.gif b/pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-embarassed.gif new file mode 100644 index 0000000000000000000000000000000000000000..963a96b8a7593b1d8bcbab073abe5ee4e539dbf6 GIT binary patch literal 331 zcmV-R0kr-{Nk%w1VG;lm0MrryDh>j~yq&6%75dW~z^P39(NxsGDE{UkxtkIEq(S-a zRKlwv+S=Lr?>hbYY~sQ?c3T&ZcN_Nh_EU3s(>Io6B&>WW`@bsw**)Ocy1bht z{*G6|uwwqUQ2+n{A^8LW0018VEC2ui01^Na000HZ;3tYwX_jM3YQ!c88=*-m*&&bO zILd=`w3KAC;8hxpif*w9ek6oqV-Z0L77fROK$BSR@5BAv-%C>6y>>#+D4e#&nz^qMDItlpp zTG728+|V&?R13PIEBW(C`uh6d*t-1sZ^XQv;oDD}iYLOV7uVO;{`xl4#4tJ{0;h@! z>)kdc3IhA?Hvj+tA^8La0018VEC2ui01^Na06+!P;3tYuX_ljS7!u|-O)I}TzP1q%xT4HOFwMJaO;2ml)!00$)141pU08x3594IX?4 o5YuAA8yXz~76K1c;3^jg77WP185Rf^u}23N0sR5^q(T4yJ1sVN5dZ)H literal 0 HcmV?d00001 diff --git a/pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-frown.gif b/pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-frown.gif new file mode 100644 index 0000000000000000000000000000000000000000..716f55e161bfebb1c3d34f0b0f40c177fc82c30b GIT binary patch literal 340 zcmV-a0jvH;Nk%w1VG;lm0MroxK_>;q#>Sw62=mns-On=0wransPVevT^YK{Dy(0YY zH)vE6x0?;Wqb>gZas1^OT0si>`ugD5y87}*#H$s=yq(wA*8cf7{`y+(+9J7|9QfT7 z`ROHiU=Y&6FaQ7mA^8LW0018VEC2ui01^Na000Hi;3tYvX_jM3N`@u~nju9hSuh^r zIEcp-wA7(NL0~2d#RP+(G!CPPA>o*KJjv_CkucCA5=K?AfF#RG2V*8BU@jL304|4P z2;PGRF@bj$et;Jf2pR_mVsIA<85|n}kQ*Bq42Ovqj*yy>6P0=h3X&9Z01yyk~2N4w%7#RW^55W%`0vQ+-6(y_*2pqz~90*;x9}yM}%$UI(7t#$D mK_3Se1{4HKM+6iG7EmeH6$V631{L5n)#CyC0qx-*Apkoyg?w!Q literal 0 HcmV?d00001 diff --git a/pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-innocent.gif b/pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-innocent.gif new file mode 100644 index 0000000000000000000000000000000000000000..334d49e0e60f2997c9ba24071764f95d9e08a5cc GIT binary patch literal 336 zcmV-W0k8f?Nk%w1VG;lm0MrryI4TI-%dP0m5~*+Y`T~ z7Rth){q{I_X%*S48uRZ|(b3V&wIKTX`u+WJzo<^$#wuY;3W|Cf{O29IkTAcaE&lpe z+P*^H)-tknA^-pYA^8LW0018VEC2ui01^Na000He;3tYwX_n)75QgVvNQ`6#5gcMm zEEG~blgXokptKAJgCU?%JT?yos!R6cPtcQWh2siHlNI2L}ifQhgX02^InZ2?-ktkqVRyZJY^Trk|lv zovp437?1~d46O)?2(1i+2NDYk8<+_Kil!K!3njA^!I#dL8x<729}*B65mC=m5gHH@ iDi9P3f*VjB3KS4HDb_qqRul{0DIT=Nk%w1VG;lm0Mrx!QauaC#>Vb6G=_5=^YB^9wrc376Sb5I-qJGf@9vZ# z5WlKU(!eVB+7tfnDXp0zyB`?BZ5IChalob*`uh6d*t+@dKGHcU+L|83yq*5~IoH?L zy`?Gp<{bX|SpWb4A^8LW0018VEC2ui01^Na000Hg;3tYyX_jM3R?Bl7&r(q;SsVx< zNd$5fv{ZsKA$SlL3&KN~a1tZRf*~1Ltkx9~2uL3&z-yb0WJDRY082|tP literal 0 HcmV?d00001 diff --git a/pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-laughing.gif b/pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-laughing.gif new file mode 100644 index 0000000000000000000000000000000000000000..82c5b182e61d32bd394acae551eff180f1eebd26 GIT binary patch literal 343 zcmV-d0jT~*Nk%w1VG;lm0Q4UK!lp8=s;1-69HWK?p_PpF=Pd8~Ygtcnp*fHAL z**;z>w3iC}`fmL6IkKB1N;3zEa}&zKpsu1;_V)HocR5-{J~BcYvE`YXhBnc@CfU=! za(Ec zG>66zv=rqr;2j)}gKqE$ekcSD?}0=WLB?AWp85)qALd+P=4)6X4oXy{bw2>K^d$ z@6ERvva+(4ib~41YUkTEn1&#?rzrOHT>1I=Y*h`+%*@WtPUPg|!@EEI_d5LgZ>^Og z-qyBKJqy*wF8}}lA^8La0018VEC2ui01^Na06+!6;3tYxX_lj?7+U61R3gAaEg8x< zT>%mSfCwURnWQF&g=Q0ZxH1ulW`QtH0>O!5%iT_X0VBy_@EkOngU8?ye~=H!t21{= z9@Uj3a_UbE88~kh5Eq7rh!7QSBn1c?0|Off1&k^`5*QE<4-gmSR<4C>Dj%C>6W(lWoQPVevT^YB^Fy&h6M z4YZgH{O~qtR1(Ci8T;lQ`uh6d*t-7xar*K{#Jrulo-Wtd*44u?{`oh#n;gQXGXDEo z_}UUC3IeK%0ssI2A^8La0018VEC2ui01^Na06+!R;3tYuX_ljSEE482&%+G^XK%|f zLKbCc4u{4-u|QG~LqamSTo?@JM3OKZAr!|Z2IzP@fY`=CIg$vA3qm46TowfLCt29I z6pDKuvnf~)83+sm9yW#?9s>^(89F=~2?!W44-6Ox2^vNza}fp^9v&G65pp936%Gg+ z6HpTy2o4oGoh+>l3Q)KVQwybl2oo*<4a3D469|nfEii|MH4`}p1_cZp0ssj%2>=2d q41Na?)CpS;4gvxWVpZcR76uLludD?Q1{SnP2NnVU0rZ&)0RTIit8@_n literal 0 HcmV?d00001 diff --git a/pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-surprised.gif b/pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-surprised.gif new file mode 100644 index 0000000000000000000000000000000000000000..0cc9bb71cca4cdeafbb248ce7e07c3708c1cbd64 GIT binary patch literal 338 zcmV-Y0j>T=Nk%w1VG;lm0Q4UK`{WwN#>SnDDC*4*{OcpiwransPVevTQacIr@mkQp zCf(06s)_=>r7UYx48o@u`uh6d*t-7rH~ji<`P&oj;5Wp)o!8ga`SV6TA_BIW5#ZWV z{`*)c32kA}f=futY?#YE7kxGD|7L}4&OEDw$hkm+~<00QS>F_H?J#bz?uEHnl42f5(9 z5O)`6Q9V2o5;YVLUK)Y`7!Nr+4GMq?85s%^2?`BGDRU798Vn2?1`%>22R{iO0u>bk z9tlA?nk*O<3zHJH6&Mp5qALj)E(mxM!Y&vII4dm@1Ov{`f*8pL3xPEVUI>D>1_uxa kNm?`6VH{N6Di;P13m6<67z+;u7qCYM7XkVK^`jvGJD~P?KL7v# literal 0 HcmV?d00001 diff --git a/pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-tongue-out.gif b/pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-tongue-out.gif new file mode 100644 index 0000000000000000000000000000000000000000..2075dc16058f1f17912167675ce5cfb9986fc71d GIT binary patch literal 328 zcmV-O0k{4~Nk%w1VG;lm0Mrx!CJF+^#>SU@3-{U*rx+Q^wrc$ABfqLn@9*x?z8(4X zSW-O=@){bmmI~g|GQXoP);cvj3|f1M8e@{G*!tYaiCEujj1NGxRN#6#tiCETo+{x{Hkzt z5k-kPvcD=V2nbmjCgL6k{uF&2nP-t0s;w<385Nx2oxDb z9T5Pp7qJl?3Kkh9oe2sCr5F$p7zPSlsUH*@54w*83=9Or4;w)r2pcU95(FL|1Th;< aDaRQH4;Tal7#Y$v#?=Au0pHUfApkpvZg^t= literal 0 HcmV?d00001 diff --git a/pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-undecided.gif b/pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-undecided.gif new file mode 100644 index 0000000000000000000000000000000000000000..bef7e257303f8243c89787e7a7f9955dd1f112e2 GIT binary patch literal 337 zcmV-X0j~Z>Nk%w1VG;lm0MroxDi#99#>R?y8~4}{%C>6#>?OadPVevTr-=vi@LATn z4rERY-qJF+n+?CCE&B3D{{3Shh?>WT0o%`b%*Voqm`dL;(4F35y zc485^n;g!+Bme*aA^8LW0018VEC2ui01^Na000Hf;3tYvX_jM3N=AnuogqakNi<9X zK?&0kwA8^tNn{?C$|IAYI1ZzT!2>}iuMddFK#NEkRl!7%6brJAnUs;)XcnA}TNBSP zxQ9;SvEfwYeSaGd2^|LqU~(QF1qBxr3Ii7x84ZVt8wCTKoSYAqc?p`G2onnpk`IOl z1`HLGj}riN2p1K12N4z&8IBDc6tEWs859;JtRB6>lf+xO9}yT19toMv8wnl`7(pKg j7zPv!OGgY81{hE&(iR3pP6ig;HPPS!_yOwPA0Yrc)=Yf3 literal 0 HcmV?d00001 diff --git a/pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-wink.gif b/pkg/plugin/richText/tinymce/plugins/emoticons/img/smiley-wink.gif new file mode 100644 index 0000000000000000000000000000000000000000..0631c7616ec8624ddeee02b633326f697ee72f80 GIT binary patch literal 350 zcmV-k0ipg!Nk%w1VG;lm0Q4UK(ZVUl#>Sn03F^-g-qAA3wransPV?|t@9*x%vmQ`7 z4E*pcw3rOOq%3t@4*K#({N^40{c-yG`rz2Q!KfI-yq*61HrBop*VoqW<}&{JS@_x# zwwfF$4Fdh~IsgCwA^8La0018VEC2ui01^Na06+!X;3tYwX_ljiFp=e23$zWxW@`*G zN?2ty6iUNT!AMdPLn89IbS7WCB_mWF$+hzY-{PWkp(?(Xf;zbH~P z3jOdj?W+^YwrakfE8fyG&5jTBz!3WS`fgM_;MltQ+c}4GO8)(E`S3`@yq&d~5!ct& z)v79NObo)O7XSbNA^8LW0018VEC2ui01^Na000He;3tYwX_jM3QifI(nn6h_*=Wyk zUB{y}v=qYOIUF#R3dZPhAVv~H;(|a2yN_5FH&J0|$eJ3kw4gj1Y?v5d#>LMV12^6BYy$1)ZKA zga!|m2?POz0R)f>4+aPl8KD{gz`+G_9vLMFQU?RU!8uyH9}*i52|cC+7S0YEK_3Vk i1|APfM-Ltb8&4_H83sg61{vHn(cc000qNZzApkp + + +

Custom dialog

+ Input some text: + + + \ No newline at end of file diff --git a/pkg/plugin/richText/tinymce/plugins/media/moxieplayer.swf b/pkg/plugin/richText/tinymce/plugins/media/moxieplayer.swf new file mode 100644 index 0000000000000000000000000000000000000000..19c771bea50c6665fe0ee5f46515e9686427dbc7 GIT binary patch literal 20017 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 + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pkg/plugin/richText/tinymce/skins/lightgray/fonts/tinymce-small.ttf b/pkg/plugin/richText/tinymce/skins/lightgray/fonts/tinymce-small.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a983e2dc4cb30880fffe00e1f0879be4d95eb4cc GIT binary patch literal 9304 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 literal 0 HcmV?d00001 diff --git a/pkg/plugin/richText/tinymce/skins/lightgray/fonts/tinymce.eot b/pkg/plugin/richText/tinymce/skins/lightgray/fonts/tinymce.eot new file mode 100644 index 0000000000000000000000000000000000000000..8838c8dc9762b9d3d6658d10601cf241062c0aa2 GIT binary patch literal 14308 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 + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pkg/plugin/richText/tinymce/skins/lightgray/fonts/tinymce.ttf b/pkg/plugin/richText/tinymce/skins/lightgray/fonts/tinymce.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ab4487febe5b98a161dcd2daa9b80d03de7c0fd8 GIT binary patch literal 14144 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 C+YCGa literal 0 HcmV?d00001 diff --git a/pkg/plugin/richText/tinymce/skins/lightgray/img/loader.gif b/pkg/plugin/richText/tinymce/skins/lightgray/img/loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..c69e937232b24ea30f01c68bbd2ebc798dcecfcb GIT binary patch literal 2608 zcmdVcdr(tX9tZGC9yiG~=H_*Q-0%n(kWqP*D#hw{AQu8;1%gl-Hrf&{2?48KX;hHy z3Ze*zEz4t3XdUFyLbNPUYlA`|B}P=N1fqtL1*}S;87#|-W9v<#G;ul(e%d3)N(^9c$d2Dz{7}?ErjNd;{EMKkCsk21~b9Gvg zDo<7L=3Z5HNbVlZUcm1eg#o#CZCJU`3IYHwM->zCd?uYrF3vKFeM}v?f+%s?E>ly|3W25ry9#NNbTx-}0ON58dTrs^ix{_1O0Wh~SVSBlH)Ajn zPn^Gbjz}PCtN@#keR&hK&Dhl-b$kZ8^S)x#dh0{7X=X%CCJk7P1PSO>T&S8I4{#Lg zb5#)o=;!ZP*1nM{cI4@(x7o27*SA()NHmrn67aN@Pmi~(i_SnrjYnwh36aG%!@i0d zqbvfa44f|?OG4ntP|nbjhEl1)Yp6ZN@yjy zy4==QmLy%t;ps3R?~f2KfTTI|2?q8dFd6^z5GF+Xa&Y)sjG)hxit80pPcOP zJ z*LW{SyGHD%hUotV+W%I}fBLAIx!8|7#}$;clKQ+{&FjDqGQ2ZNx(lYM3*%~}ILnao zM`aui55~ZFJlu^!5rdA9Q_7H68H_;##u{x(Yn-vSfIRCb^Nqsg zGRS!Egm>h+o<}LeV4&CLReo9FrDjDvs}8?JwC)#Qs|ie=r?~xUh)&*d`Fx>FG}%X# zNdtDHBKhLPC0wpooFDAQKL%*6T|ULH$=wX!NhcasgD3d;-d$I6yRK3yN+E~C1335_iLOt+*9uvSZ`>*KA}vm}08wRq=>5l|t*Na&jR z-C1&C`nkEk#sB|@yyt-#fXngP04My zm7u$Q%EJbHp`>~`5W&L{W!6`y&}LMS;jfUpgO~7TLVMRZ9IC)IZp0A${`yp0{&wco z#1nx@XMkhqeK%7?RE7JdLr1^nwFfaJ0Q&Lv?WNJ%9}VSJsNY2+UYs2%EU0J~ayFXv zi*?7KCXQHkD)O6!0Q%4N+HTODHxJ{kQSuQX$l-rSwkwh(zMkdfzxyGwl@yHC)C4p< z&n2%8#M?)Q@mgHL1ot8`SFdSEj9ye|jHy+U8#@HoUExG=@AVkRAe_qYm4EpzK6L*& zh`)26?V#f4#_h^P9G^%>h2-H3)$QP zQovu6J9qDvsxqweDdNNa!Lb?L4_UF{tLX_nN7r0U_vF14YKcGR-*Gl} zx3oG)bzf|65dBxD-;2ZCp??K;+TuQ9onnK?==5hzbkb^r_g>z4#D8mcv8(+XdoszA zCx-qhdgxMNMotj}SiL_6V(tLcsK7(M(r(%u<}QrVfOvyK6_;~NOTlPGfX@M7S5YQF z&*$(ylJMHJt^_aQeu{C6NaTE$G3HNN@_SnN8YcaKn%`)F@~L1x+ah7-gEJPpc6w%3 zyX}r+Qk$4RHZzfH){e~F*qJ{d*L8a6n4;U?+{de0-t)mal#TVxe)3F}^UBh+zd T)6_**#cgp_+?JL9(ew3BlNF>u literal 0 HcmV?d00001 diff --git a/pkg/plugin/richText/tinymce/skins/lightgray/img/object.gif b/pkg/plugin/richText/tinymce/skins/lightgray/img/object.gif new file mode 100644 index 0000000000000000000000000000000000000000..cccd7f023fb80908cb33bb7d9604236cd21b7ae7 GIT binary patch literal 152 zcmV;J0B8S4Nk%w1VG#fg0J9GO<>lo+KR<78Z?v?uS65g4{r%Y3*xlXT%F4>`@9+2b z_ww@cot>Tk|Nk>HGXMYpA^8LW000jFEC2ui01*HU000C<(8)=wd#<&tyXIMjHBV`d zBSi|xsj3(;nD0kQ0aJq8eLH~x02P|t2!_J&Wqb%0io?#xD"; + ed.setContent(ed.getContent()+iframeRubric); + $(editor.element).find('textarea')[0].value = ed.getContent(); + } + } + }); + ed.insertContent('Main button'); + ed.label = 'My Button'; + } + }); + }; + tinymce.init(this.options.tinymce); + }; + + RichText.prototype.updateEditor = function(field, annotation) { + var text = typeof annotation.text!='undefined'?annotation.text:''; + tinymce.activeEditor.setContent(text); + $(field).remove(); //this is the auto create field by annotator and it is not necessary + } + + RichText.prototype.updateViewer = function(field, annotation) { + var textDiv = $(field.parentNode).find('div:first-of-type')[0]; + textDiv.innerHTML =annotation.text; + $(textDiv).addClass('richText-annotation'); + $(field).remove(); //this is the auto create field by annotator and it is not necessary + } + + return RichText; + +})(Annotator.Plugin); + diff --git a/src/plugin/richText/tinymce/langs/readme.md b/src/plugin/richText/tinymce/langs/readme.md new file mode 100644 index 000000000..a52bf03f9 --- /dev/null +++ b/src/plugin/richText/tinymce/langs/readme.md @@ -0,0 +1,3 @@ +This is where language files should be placed. + +Please DO NOT translate these directly use this service: https://www.transifex.com/projects/p/tinymce/ diff --git a/src/plugin/richText/tinymce/license.txt b/src/plugin/richText/tinymce/license.txt new file mode 100644 index 000000000..1837b0acb --- /dev/null +++ b/src/plugin/richText/tinymce/license.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/src/plugin/richText/tinymce/plugins/advlist/plugin.min.js b/src/plugin/richText/tinymce/plugins/advlist/plugin.min.js new file mode 100644 index 000000000..18c5aff74 --- /dev/null +++ b/src/plugin/richText/tinymce/plugins/advlist/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("advlist",function(e){function t(e,t){var n=[];return tinymce.each(t.split(/[ ,]/),function(e){n.push({text:e.replace(/\-/g," ").replace(/\b\w/g,function(e){return e.toUpperCase()}),data:"default"==e?"":e})}),n}function n(t,n){e.undoManager.transact(function(){var r,i=e.dom,o=e.selection;r=i.getParent(o.getNode(),"ol,ul"),r&&r.nodeName==t&&n!==!1||e.execCommand("UL"==t?"InsertUnorderedList":"InsertOrderedList"),n=n===!1?a[t]:n,a[t]=n,r=i.getParent(o.getNode(),"ol,ul"),r&&(i.setStyle(r,"listStyleType",n?n:null),r.removeAttribute("data-mce-style")),e.focus()})}function r(t){var n=e.dom.getStyle(e.dom.getParent(e.selection.getNode(),"ol,ul"),"listStyleType")||"";t.control.items().each(function(e){e.active(e.settings.data===n)})}var i,o,a={};i=t("OL",e.getParam("advlist_number_styles","default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman")),o=t("UL",e.getParam("advlist_bullet_styles","default,circle,disc,square")),e.addButton("numlist",{type:"splitbutton",tooltip:"Numbered list",menu:i,onshow:r,onselect:function(e){n("OL",e.control.settings.data)},onclick:function(){n("OL",!1)}}),e.addButton("bullist",{type:"splitbutton",tooltip:"Bullet list",menu:o,onshow:r,onselect:function(e){n("UL",e.control.settings.data)},onclick:function(){n("UL",!1)}})}); \ No newline at end of file diff --git a/src/plugin/richText/tinymce/plugins/anchor/plugin.min.js b/src/plugin/richText/tinymce/plugins/anchor/plugin.min.js new file mode 100644 index 000000000..4ad2c1350 --- /dev/null +++ b/src/plugin/richText/tinymce/plugins/anchor/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("anchor",function(e){function t(){var t=e.selection.getNode(),n="",r="A"==t.tagName&&""===e.dom.getAttrib(t,"href");r&&(n=t.name||t.id||""),e.windowManager.open({title:"Anchor",body:{type:"textbox",name:"name",size:40,label:"Name",value:n},onsubmit:function(n){var i=n.data.name;r?t.id=i:(e.selection.collapse(!0),e.execCommand("mceInsertContent",!1,e.dom.createHTML("a",{id:i})))}})}e.addCommand("mceAnchor",t),e.addButton("anchor",{icon:"anchor",tooltip:"Anchor",onclick:t,stateSelector:"a:not([href])"}),e.addMenuItem("anchor",{icon:"anchor",text:"Anchor",context:"insert",onclick:t})}); \ No newline at end of file diff --git a/src/plugin/richText/tinymce/plugins/autolink/plugin.min.js b/src/plugin/richText/tinymce/plugins/autolink/plugin.min.js new file mode 100644 index 000000000..f8f9d61c3 --- /dev/null +++ b/src/plugin/richText/tinymce/plugins/autolink/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("autolink",function(e){function t(e){i(e,-1,"(",!0)}function n(e){i(e,0,"",!0)}function r(e){i(e,-1,"",!1)}function i(e,t,n){function r(e,t){if(0>t&&(t=0),3==e.nodeType){var n=e.data.length;t>n&&(t=n)}return t}function i(e,t){1!=e.nodeType||e.hasChildNodes()?s.setStart(e,r(e,t)):s.setStartBefore(e)}function o(e,t){1!=e.nodeType||e.hasChildNodes()?s.setEnd(e,r(e,t)):s.setEndAfter(e)}var s,l,c,u,d,f,h,m,p,g;if("A"!=e.selection.getNode().tagName){if(s=e.selection.getRng(!0).cloneRange(),s.startOffset<5){if(m=s.endContainer.previousSibling,!m){if(!s.endContainer.firstChild||!s.endContainer.firstChild.nextSibling)return;m=s.endContainer.firstChild.nextSibling}if(p=m.length,i(m,p),o(m,p),s.endOffset<5)return;l=s.endOffset,u=m}else{if(u=s.endContainer,3!=u.nodeType&&u.firstChild){for(;3!=u.nodeType&&u.firstChild;)u=u.firstChild;3==u.nodeType&&(i(u,0),o(u,u.nodeValue.length))}l=1==s.endOffset?2:s.endOffset-1-t}c=l;do i(u,l>=2?l-2:0),o(u,l>=1?l-1:0),l-=1,g=s.toString();while(" "!=g&&""!==g&&160!=g.charCodeAt(0)&&l-2>=0&&g!=n);s.toString()==n||160==s.toString().charCodeAt(0)?(i(u,l),o(u,c),l+=1):0===s.startOffset?(i(u,0),o(u,c)):(i(u,l),o(u,c)),f=s.toString(),"."==f.charAt(f.length-1)&&o(u,c-1),f=s.toString(),h=f.match(a),h&&("www."==h[1]?h[1]="http://www.":/@$/.test(h[1])&&!/^mailto:/.test(h[1])&&(h[1]="mailto:"+h[1]),d=e.selection.getBookmark(),e.selection.setRng(s),e.execCommand("createlink",!1,h[1]+h[2]),e.selection.moveToBookmark(d),e.nodeChanged())}}var o,a=/^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|(?:mailto:)?[A-Z0-9._%+\-]+@)(.+)$/i;return e.settings.autolink_pattern&&(a=e.settings.autolink_pattern),e.on("keydown",function(t){return 13==t.keyCode?r(e):void 0}),tinymce.Env.ie?void e.on("focus",function(){if(!o){o=!0;try{e.execCommand("AutoUrlDetect",!1,!0)}catch(t){}}}):(e.on("keypress",function(n){return 41==n.keyCode?t(e):void 0}),void e.on("keyup",function(t){return 32==t.keyCode?n(e):void 0}))}); \ No newline at end of file diff --git a/src/plugin/richText/tinymce/plugins/autoresize/plugin.min.js b/src/plugin/richText/tinymce/plugins/autoresize/plugin.min.js new file mode 100644 index 000000000..d96459edf --- /dev/null +++ b/src/plugin/richText/tinymce/plugins/autoresize/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("autoresize",function(e){function t(){return e.plugins.fullscreen&&e.plugins.fullscreen.isFullscreen()}function n(r){var a,s,l,c,u,d,f,h,m,p,g,v,y=tinymce.DOM;if(s=e.getDoc()){if(l=s.body,c=s.documentElement,u=i.autoresize_min_height,!l||r&&"setcontent"===r.type&&r.initial||t())return void(l&&c&&(l.style.overflowY="auto",c.style.overflowY="auto"));f=e.dom.getStyle(l,"margin-top",!0),h=e.dom.getStyle(l,"margin-bottom",!0),m=e.dom.getStyle(l,"padding-top",!0),p=e.dom.getStyle(l,"padding-bottom",!0),g=e.dom.getStyle(l,"border-top-width",!0),v=e.dom.getStyle(l,"border-bottom-width",!0),d=l.offsetHeight+parseInt(f,10)+parseInt(h,10)+parseInt(m,10)+parseInt(p,10)+parseInt(g,10)+parseInt(v,10),(isNaN(d)||0>=d)&&(d=tinymce.Env.ie?l.scrollHeight:tinymce.Env.webkit&&0===l.clientHeight?0:l.offsetHeight),d>i.autoresize_min_height&&(u=d),i.autoresize_max_height&&d>i.autoresize_max_height?(u=i.autoresize_max_height,l.style.overflowY="auto",c.style.overflowY="auto"):(l.style.overflowY="hidden",c.style.overflowY="hidden",l.scrollTop=0),u!==o&&(a=u-o,y.setStyle(e.iframeElement,"height",u+"px"),o=u,tinymce.isWebKit&&0>a&&n(r))}}function r(t,i,o){tinymce.util.Delay.setEditorTimeout(e,function(){n({}),t--?r(t,i,o):o&&o()},i)}var i=e.settings,o=0;e.settings.inline||(i.autoresize_min_height=parseInt(e.getParam("autoresize_min_height",e.getElement().offsetHeight),10),i.autoresize_max_height=parseInt(e.getParam("autoresize_max_height",0),10),e.on("init",function(){var t,n;t=e.getParam("autoresize_overflow_padding",1),n=e.getParam("autoresize_bottom_margin",50),t!==!1&&e.dom.setStyles(e.getBody(),{paddingLeft:t,paddingRight:t}),n!==!1&&e.dom.setStyles(e.getBody(),{paddingBottom:n})}),e.on("nodechange setcontent keyup FullscreenStateChanged",n),e.getParam("autoresize_on_init",!0)&&e.on("init",function(){r(20,100,function(){r(5,1e3)})}),e.addCommand("mceAutoResize",n))}); \ No newline at end of file diff --git a/src/plugin/richText/tinymce/plugins/autosave/plugin.min.js b/src/plugin/richText/tinymce/plugins/autosave/plugin.min.js new file mode 100644 index 000000000..ca8c2307e --- /dev/null +++ b/src/plugin/richText/tinymce/plugins/autosave/plugin.min.js @@ -0,0 +1 @@ +tinymce._beforeUnloadHandler=function(){var e;return tinymce.each(tinymce.editors,function(t){t.plugins.autosave&&t.plugins.autosave.storeDraft(),!e&&t.isDirty()&&t.getParam("autosave_ask_before_unload",!0)&&(e=t.translate("You have unsaved changes are you sure you want to navigate away?"))}),e},tinymce.PluginManager.add("autosave",function(e){function t(e,t){var n={s:1e3,m:6e4};return e=/^(\d+)([ms]?)$/.exec(""+(e||t)),(e[2]?n[e[2]]:1)*parseInt(e,10)}function n(){var e=parseInt(h.getItem(u+"time"),10)||0;return(new Date).getTime()-e>f.autosave_retention?(r(!1),!1):!0}function r(t){h.removeItem(u+"draft"),h.removeItem(u+"time"),t!==!1&&e.fire("RemoveDraft")}function i(){!c()&&e.isDirty()&&(h.setItem(u+"draft",e.getContent({format:"raw",no_events:!0})),h.setItem(u+"time",(new Date).getTime()),e.fire("StoreDraft"))}function o(){n()&&(e.setContent(h.getItem(u+"draft"),{format:"raw"}),e.fire("RestoreDraft"))}function a(){d||(setInterval(function(){e.removed||i()},f.autosave_interval),d=!0)}function s(){var t=this;t.disabled(!n()),e.on("StoreDraft RestoreDraft RemoveDraft",function(){t.disabled(!n())}),a()}function l(){e.undoManager.beforeChange(),o(),r(),e.undoManager.add()}function c(t){var n=e.settings.forced_root_block;return t=tinymce.trim("undefined"==typeof t?e.getBody().innerHTML:t),""===t||new RegExp("^<"+n+"[^>]*>((\xa0| |[ ]|]*>)+?|)|
$","i").test(t)}var u,d,f=e.settings,h=tinymce.util.LocalStorage;u=f.autosave_prefix||"tinymce-autosave-{path}{query}-{id}-",u=u.replace(/\{path\}/g,document.location.pathname),u=u.replace(/\{query\}/g,document.location.search),u=u.replace(/\{id\}/g,e.id),f.autosave_interval=t(f.autosave_interval,"30s"),f.autosave_retention=t(f.autosave_retention,"20m"),e.addButton("restoredraft",{title:"Restore last draft",onclick:l,onPostRender:s}),e.addMenuItem("restoredraft",{text:"Restore last draft",onclick:l,onPostRender:s,context:"file"}),e.settings.autosave_restore_when_empty!==!1&&(e.on("init",function(){n()&&c()&&o()}),e.on("saveContent",function(){r()})),window.onbeforeunload=tinymce._beforeUnloadHandler,this.hasDraft=n,this.storeDraft=i,this.restoreDraft=o,this.removeDraft=r,this.isEmpty=c}); \ No newline at end of file diff --git a/src/plugin/richText/tinymce/plugins/bbcode/plugin.min.js b/src/plugin/richText/tinymce/plugins/bbcode/plugin.min.js new file mode 100644 index 000000000..5e193fcca --- /dev/null +++ b/src/plugin/richText/tinymce/plugins/bbcode/plugin.min.js @@ -0,0 +1 @@ +!function(){tinymce.create("tinymce.plugins.BBCodePlugin",{init:function(e){var t=this,n=e.getParam("bbcode_dialect","punbb").toLowerCase();e.on("beforeSetContent",function(e){e.content=t["_"+n+"_bbcode2html"](e.content)}),e.on("postProcess",function(e){e.set&&(e.content=t["_"+n+"_bbcode2html"](e.content)),e.get&&(e.content=t["_"+n+"_html2bbcode"](e.content))})},getInfo:function(){return{longname:"BBCode Plugin",author:"Ephox Corp",authorurl:"http://www.tinymce.com",infourl:"http://www.tinymce.com/wiki.php/Plugin:bbcode"}},_punbb_html2bbcode:function(e){function t(t,n){e=e.replace(t,n)}return e=tinymce.trim(e),t(/(.*?)<\/a>/gi,"[url=$1]$2[/url]"),t(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),t(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),t(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),t(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),t(/(.*?)<\/span>/gi,"[color=$1]$2[/color]"),t(/(.*?)<\/font>/gi,"[color=$1]$2[/color]"),t(/(.*?)<\/span>/gi,"[size=$1]$2[/size]"),t(/(.*?)<\/font>/gi,"$1"),t(//gi,"[img]$1[/img]"),t(/(.*?)<\/span>/gi,"[code]$1[/code]"),t(/(.*?)<\/span>/gi,"[quote]$1[/quote]"),t(/(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"),t(/(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"),t(/(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"),t(/(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"),t(/(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"),t(/(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"),t(/<\/(strong|b)>/gi,"[/b]"),t(/<(strong|b)>/gi,"[b]"),t(/<\/(em|i)>/gi,"[/i]"),t(/<(em|i)>/gi,"[i]"),t(/<\/u>/gi,"[/u]"),t(/(.*?)<\/span>/gi,"[u]$1[/u]"),t(//gi,"[u]"),t(/]*>/gi,"[quote]"),t(/<\/blockquote>/gi,"[/quote]"),t(/
/gi,"\n"),t(//gi,"\n"),t(/
/gi,"\n"),t(/

/gi,""),t(/<\/p>/gi,"\n"),t(/ |\u00a0/gi," "),t(/"/gi,'"'),t(/</gi,"<"),t(/>/gi,">"),t(/&/gi,"&"),e},_punbb_bbcode2html:function(e){function t(t,n){e=e.replace(t,n)}return e=tinymce.trim(e),t(/\n/gi,"
"),t(/\[b\]/gi,""),t(/\[\/b\]/gi,""),t(/\[i\]/gi,""),t(/\[\/i\]/gi,""),t(/\[u\]/gi,""),t(/\[\/u\]/gi,""),t(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'$2'),t(/\[url\](.*?)\[\/url\]/gi,'$1'),t(/\[img\](.*?)\[\/img\]/gi,''),t(/\[color=(.*?)\](.*?)\[\/color\]/gi,'$2'),t(/\[code\](.*?)\[\/code\]/gi,'$1 '),t(/\[quote.*?\](.*?)\[\/quote\]/gi,'$1 '),e}}),tinymce.PluginManager.add("bbcode",tinymce.plugins.BBCodePlugin)}(); \ No newline at end of file diff --git a/src/plugin/richText/tinymce/plugins/charmap/plugin.min.js b/src/plugin/richText/tinymce/plugins/charmap/plugin.min.js new file mode 100644 index 000000000..fdad478e0 --- /dev/null +++ b/src/plugin/richText/tinymce/plugins/charmap/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("charmap",function(e){function t(){return[["160","no-break space"],["173","soft hyphen"],["34","quotation mark"],["162","cent sign"],["8364","euro sign"],["163","pound sign"],["165","yen sign"],["169","copyright sign"],["174","registered sign"],["8482","trade mark sign"],["8240","per mille sign"],["181","micro sign"],["183","middle dot"],["8226","bullet"],["8230","three dot leader"],["8242","minutes / feet"],["8243","seconds / inches"],["167","section sign"],["182","paragraph sign"],["223","sharp s / ess-zed"],["8249","single left-pointing angle quotation mark"],["8250","single right-pointing angle quotation mark"],["171","left pointing guillemet"],["187","right pointing guillemet"],["8216","left single quotation mark"],["8217","right single quotation mark"],["8220","left double quotation mark"],["8221","right double quotation mark"],["8218","single low-9 quotation mark"],["8222","double low-9 quotation mark"],["60","less-than sign"],["62","greater-than sign"],["8804","less-than or equal to"],["8805","greater-than or equal to"],["8211","en dash"],["8212","em dash"],["175","macron"],["8254","overline"],["164","currency sign"],["166","broken bar"],["168","diaeresis"],["161","inverted exclamation mark"],["191","turned question mark"],["710","circumflex accent"],["732","small tilde"],["176","degree sign"],["8722","minus sign"],["177","plus-minus sign"],["247","division sign"],["8260","fraction slash"],["215","multiplication sign"],["185","superscript one"],["178","superscript two"],["179","superscript three"],["188","fraction one quarter"],["189","fraction one half"],["190","fraction three quarters"],["402","function / florin"],["8747","integral"],["8721","n-ary sumation"],["8734","infinity"],["8730","square root"],["8764","similar to"],["8773","approximately equal to"],["8776","almost equal to"],["8800","not equal to"],["8801","identical to"],["8712","element of"],["8713","not an element of"],["8715","contains as member"],["8719","n-ary product"],["8743","logical and"],["8744","logical or"],["172","not sign"],["8745","intersection"],["8746","union"],["8706","partial differential"],["8704","for all"],["8707","there exists"],["8709","diameter"],["8711","backward difference"],["8727","asterisk operator"],["8733","proportional to"],["8736","angle"],["180","acute accent"],["184","cedilla"],["170","feminine ordinal indicator"],["186","masculine ordinal indicator"],["8224","dagger"],["8225","double dagger"],["192","A - grave"],["193","A - acute"],["194","A - circumflex"],["195","A - tilde"],["196","A - diaeresis"],["197","A - ring above"],["198","ligature AE"],["199","C - cedilla"],["200","E - grave"],["201","E - acute"],["202","E - circumflex"],["203","E - diaeresis"],["204","I - grave"],["205","I - acute"],["206","I - circumflex"],["207","I - diaeresis"],["208","ETH"],["209","N - tilde"],["210","O - grave"],["211","O - acute"],["212","O - circumflex"],["213","O - tilde"],["214","O - diaeresis"],["216","O - slash"],["338","ligature OE"],["352","S - caron"],["217","U - grave"],["218","U - acute"],["219","U - circumflex"],["220","U - diaeresis"],["221","Y - acute"],["376","Y - diaeresis"],["222","THORN"],["224","a - grave"],["225","a - acute"],["226","a - circumflex"],["227","a - tilde"],["228","a - diaeresis"],["229","a - ring above"],["230","ligature ae"],["231","c - cedilla"],["232","e - grave"],["233","e - acute"],["234","e - circumflex"],["235","e - diaeresis"],["236","i - grave"],["237","i - acute"],["238","i - circumflex"],["239","i - diaeresis"],["240","eth"],["241","n - tilde"],["242","o - grave"],["243","o - acute"],["244","o - circumflex"],["245","o - tilde"],["246","o - diaeresis"],["248","o slash"],["339","ligature oe"],["353","s - caron"],["249","u - grave"],["250","u - acute"],["251","u - circumflex"],["252","u - diaeresis"],["253","y - acute"],["254","thorn"],["255","y - diaeresis"],["913","Alpha"],["914","Beta"],["915","Gamma"],["916","Delta"],["917","Epsilon"],["918","Zeta"],["919","Eta"],["920","Theta"],["921","Iota"],["922","Kappa"],["923","Lambda"],["924","Mu"],["925","Nu"],["926","Xi"],["927","Omicron"],["928","Pi"],["929","Rho"],["931","Sigma"],["932","Tau"],["933","Upsilon"],["934","Phi"],["935","Chi"],["936","Psi"],["937","Omega"],["945","alpha"],["946","beta"],["947","gamma"],["948","delta"],["949","epsilon"],["950","zeta"],["951","eta"],["952","theta"],["953","iota"],["954","kappa"],["955","lambda"],["956","mu"],["957","nu"],["958","xi"],["959","omicron"],["960","pi"],["961","rho"],["962","final sigma"],["963","sigma"],["964","tau"],["965","upsilon"],["966","phi"],["967","chi"],["968","psi"],["969","omega"],["8501","alef symbol"],["982","pi symbol"],["8476","real part symbol"],["978","upsilon - hook symbol"],["8472","Weierstrass p"],["8465","imaginary part"],["8592","leftwards arrow"],["8593","upwards arrow"],["8594","rightwards arrow"],["8595","downwards arrow"],["8596","left right arrow"],["8629","carriage return"],["8656","leftwards double arrow"],["8657","upwards double arrow"],["8658","rightwards double arrow"],["8659","downwards double arrow"],["8660","left right double arrow"],["8756","therefore"],["8834","subset of"],["8835","superset of"],["8836","not a subset of"],["8838","subset of or equal to"],["8839","superset of or equal to"],["8853","circled plus"],["8855","circled times"],["8869","perpendicular"],["8901","dot operator"],["8968","left ceiling"],["8969","right ceiling"],["8970","left floor"],["8971","right floor"],["9001","left-pointing angle bracket"],["9002","right-pointing angle bracket"],["9674","lozenge"],["9824","black spade suit"],["9827","black club suit"],["9829","black heart suit"],["9830","black diamond suit"],["8194","en space"],["8195","em space"],["8201","thin space"],["8204","zero width non-joiner"],["8205","zero width joiner"],["8206","left-to-right mark"],["8207","right-to-left mark"]]}function n(e){return tinymce.util.Tools.grep(e,function(e){return l(e)&&2==e.length})}function r(e){return l(e)?[].concat(n(e)):"function"==typeof e?e():[]}function i(t){var n=e.settings;return n.charmap&&(t=r(n.charmap)),n.charmap_append?[].concat(t).concat(r(n.charmap_append)):t}function o(){return i(t())}function a(t){e.fire("insertCustomChar",{chr:t}).chr,e.execCommand("mceInsertContent",!1,t)}function s(){function t(e){for(;e;){if("TD"==e.nodeName)return e;e=e.parentNode}}var n,r,i,s;n='';var l=o(),c=Math.min(l.length,25),u=Math.ceil(l.length/c);for(i=0;u>i;i++){for(n+="",r=0;c>r;r++){var d=i*c+r;if(d
'+(f?String.fromCharCode(parseInt(f[0],10)):" ")+"
"}else n+="
"}n+="";var h={type:"container",html:n,onclick:function(e){var n=e.target;/^(TD|DIV)$/.test(n.nodeName)&&t(n).firstChild&&(a(tinymce.trim(n.innerText||n.textContent)),e.ctrlKey||s.close())},onmouseover:function(e){var n=t(e.target);n&&n.firstChild?(s.find("#preview").text(n.firstChild.firstChild.data),s.find("#previewTitle").text(n.title)):(s.find("#preview").text(" "),s.find("#previewTitle").text(" "))}};s=e.windowManager.open({title:"Special character",spacing:10,padding:10,items:[h,{type:"container",layout:"flex",direction:"column",align:"center",spacing:5,minWidth:160,minHeight:160,items:[{type:"label",name:"preview",text:" ",style:"font-size: 40px; text-align: center",border:1,minWidth:140,minHeight:80},{type:"label",name:"previewTitle",text:" ",style:"text-align: center",border:1,minWidth:140,minHeight:80}]}],buttons:[{text:"Close",onclick:function(){s.close()}}]})}var l=tinymce.util.Tools.isArray;return e.addCommand("mceShowCharmap",s),e.addButton("charmap",{icon:"charmap",tooltip:"Special character",cmd:"mceShowCharmap"}),e.addMenuItem("charmap",{icon:"charmap",text:"Special character",cmd:"mceShowCharmap",context:"insert"}),{getCharMap:o,insertChar:a}}); \ No newline at end of file diff --git a/src/plugin/richText/tinymce/plugins/code/plugin.min.js b/src/plugin/richText/tinymce/plugins/code/plugin.min.js new file mode 100644 index 000000000..d9e43860c --- /dev/null +++ b/src/plugin/richText/tinymce/plugins/code/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("code",function(e){function t(){var t=e.windowManager.open({title:"Source code",body:{type:"textbox",name:"code",multiline:!0,minWidth:e.getParam("code_dialog_width",600),minHeight:e.getParam("code_dialog_height",Math.min(tinymce.DOM.getViewPort().h-200,500)),spellcheck:!1,style:"direction: ltr; text-align: left"},onSubmit:function(t){e.focus(),e.undoManager.transact(function(){e.setContent(t.data.code)}),e.selection.setCursorLocation(),e.nodeChanged()}});t.find("#code").value(e.getContent({source_view:!0}))}e.addCommand("mceCodeEditor",t),e.addButton("code",{icon:"code",tooltip:"Source code",onclick:t}),e.addMenuItem("code",{icon:"code",text:"Source code",context:"tools",onclick:t})}); \ No newline at end of file diff --git a/src/plugin/richText/tinymce/plugins/codesample/css/prism.css b/src/plugin/richText/tinymce/plugins/codesample/css/prism.css new file mode 100644 index 000000000..28622b521 --- /dev/null +++ b/src/plugin/richText/tinymce/plugins/codesample/css/prism.css @@ -0,0 +1,138 @@ +/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript */ +/** + * prism.js default theme for JavaScript, CSS and HTML + * Based on dabblet (http://dabblet.com) + * @author Lea Verou + */ + +code[class*="language-"], +pre[class*="language-"] { + color: black; + text-shadow: 0 1px white; + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + direction: ltr; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, +code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { + text-shadow: none; + background: #b3d4fc; +} + +pre[class*="language-"]::selection, pre[class*="language-"] ::selection, +code[class*="language-"]::selection, code[class*="language-"] ::selection { + text-shadow: none; + background: #b3d4fc; +} + +@media print { + code[class*="language-"], + pre[class*="language-"] { + text-shadow: none; + } +} + +/* Code blocks */ +pre[class*="language-"] { + padding: 1em; + margin: .5em 0; + overflow: auto; +} + +:not(pre) > code[class*="language-"], +pre[class*="language-"] { + background: #f5f2f0; +} + +/* Inline code */ +:not(pre) > code[class*="language-"] { + padding: .1em; + border-radius: .3em; +} + +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: slategray; +} + +.token.punctuation { + color: #999; +} + +.namespace { + opacity: .7; +} + +.token.property, +.token.tag, +.token.boolean, +.token.number, +.token.constant, +.token.symbol, +.token.deleted { + color: #905; +} + +.token.selector, +.token.attr-name, +.token.string, +.token.char, +.token.builtin, +.token.inserted { + color: #690; +} + +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string { + color: #a67f59; + background: hsla(0, 0%, 100%, .5); +} + +.token.atrule, +.token.attr-value, +.token.keyword { + color: #07a; +} + +.token.function { + color: #DD4A68; +} + +.token.regex, +.token.important, +.token.variable { + color: #e90; +} + +.token.important, +.token.bold { + font-weight: bold; +} +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} + diff --git a/src/plugin/richText/tinymce/plugins/codesample/plugin.min.js b/src/plugin/richText/tinymce/plugins/codesample/plugin.min.js new file mode 100644 index 000000000..e1c92cd22 --- /dev/null +++ b/src/plugin/richText/tinymce/plugins/codesample/plugin.min.js @@ -0,0 +1 @@ +!function(e,t){"use strict";function n(e,t){for(var n,r=[],o=0;oe.length)break e;if(!(g instanceof i)){u.lastIndex=0;var v=u.exec(g);if(v){f&&(h=v[1].length);var y=v.index-1+h,v=v[0].slice(h),b=v.length,x=y+b,C=g.slice(0,y+1),w=g.slice(x+1),N=[p,1];C&&N.push(C);var E=new i(s,d?n.tokenize(v,d):v,m);N.push(E),w&&N.push(w),Array.prototype.splice.apply(o,N)}}}}}return o},hooks:{all:{},add:function(e,t){var r=n.hooks.all;r[e]=r[e]||[],r[e].push(t)},run:function(e,t){var r=n.hooks.all[e];if(r&&r.length)for(var i,o=0;i=r[o++];)i(t)}}},r=n.Token=function(e,t,n){this.type=e,this.content=t,this.alias=n};return r.stringify=function(e,t,i){if("string"==typeof e)return e;if("Array"===n.util.type(e))return e.map(function(n){return r.stringify(n,t,e)}).join("");var o={type:e.type,content:r.stringify(e.content,t,i),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:i};if("comment"==o.type&&(o.attributes.spellcheck="true"),e.alias){var a="Array"===n.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(o.classes,a)}n.hooks.run("wrap",o);var s="";for(var l in o.attributes)s+=(s?" ":"")+l+'="'+(o.attributes[l]||"")+'"';return"<"+o.tag+' class="'+o.classes.join(" ")+'" '+s+">"+o.content+""},t.document?void 0:t.addEventListener?(t.addEventListener("message",function(e){var r=JSON.parse(e.data),i=r.language,o=r.code,a=r.immediateClose;t.postMessage(n.highlight(o,n.languages[i],i)),a&&t.close()},!1),t.Prism):t.Prism}();return"undefined"!=typeof module&&module.exports&&(module.exports=n),"undefined"!=typeof global&&(global.Prism=n),n.languages.markup={comment://,prolog:/<\?[\w\W]+?\?>/,doctype://,cdata://i,tag:{pattern:/<\/?[^\s>\/=.]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\w\W])*\1|[^\s'">=]+))?)*\s*\/?>/i,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:('|")[\w\W]*?(\1)|[^\s>]+)/i,inside:{punctuation:/[=>"']/}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},n.hooks.add("wrap",function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))}),n.languages.xml=n.languages.markup,n.languages.html=n.languages.markup,n.languages.mathml=n.languages.markup,n.languages.svg=n.languages.markup,n.languages.css={comment:/\/\*[\w\W]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^\{\}\s][^\{\};]*?(?=\s*\{)/,string:/("|')(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1/,property:/(\b|\B)[\w-]+(?=\s*:)/i,important:/\B!important\b/i,"function":/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},n.languages.css.atrule.inside.rest=n.util.clone(n.languages.css),n.languages.markup&&(n.languages.insertBefore("markup","tag",{style:{pattern:/[\w\W]*?<\/style>/i,inside:{tag:{pattern:/|<\/style>/i,inside:n.languages.markup.tag.inside},rest:n.languages.css},alias:"language-css"}}),n.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|').*?\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:n.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:n.languages.css}},alias:"language-css"}},n.languages.markup.tag)),n.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\w\W]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:/(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(true|false)\b/,"function":/[a-z0-9_]+(?=\()/i,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/},n.languages.javascript=n.languages.extend("clike",{keyword:/\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/,number:/\b-?(0x[\dA-Fa-f]+|0b[01]+|0o[0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/,"function":/[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\()/i}),n.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^\/])\/(?!\/)(\[.+?]|\\.|[^\/\\\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0}}),n.languages.insertBefore("javascript","class-name",{"template-string":{pattern:/`(?:\\`|\\?[^`])*`/,inside:{interpolation:{pattern:/\$\{[^}]+\}/,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:n.languages.javascript}},string:/[\s\S]+/}}}),n.languages.markup&&n.languages.insertBefore("markup","tag",{script:{pattern:/[\w\W]*?<\/script>/i,inside:{tag:{pattern:/|<\/script>/i,inside:n.languages.markup.tag.inside},rest:n.languages.javascript},alias:"language-javascript"}}),n.languages.js=n.languages.javascript,n.languages.c=n.languages.extend("clike",{keyword:/\b(asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,operator:/\-[>-]?|\+\+?|!=?|<>?=?|==?|&&?|\|?\||[~^%?*\/]/,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)[ful]*\b/i}),n.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+([^\r\n\\]|\\.|\\(?:\r\n?|\n))*/im,lookbehind:!0,alias:"property",inside:{string:{pattern:/(#\s*include\s*)(<.+?>|("|')(\\?.)+?\3)/,lookbehind:!0}}}}),delete n.languages.c["class-name"],delete n.languages.c["boolean"],n.languages.csharp=n.languages.extend("clike",{keyword:/\b(abstract|as|async|await|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|do|double|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|goto|if|implicit|in|int|interface|internal|is|lock|long|namespace|new|null|object|operator|out|override|params|private|protected|public|readonly|ref|return|sbyte|sealed|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|virtual|void|volatile|while|add|alias|ascending|async|await|descending|dynamic|from|get|global|group|into|join|let|orderby|partial|remove|select|set|value|var|where|yield)\b/,string:[/@("|')(\1\1|\\\1|\\?(?!\1)[\s\S])*\1/,/("|')(\\?.)*?\1/],number:/\b-?(0x[\da-f]+|\d*\.?\d+)\b/i}),n.languages.insertBefore("csharp","keyword",{preprocessor:{pattern:/(^\s*)#.*/m,lookbehind:!0}}),n.languages.cpp=n.languages.extend("c",{keyword:/\b(alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,"boolean":/\b(true|false)\b/,operator:/[-+]{1,2}|!=?|<{1,2}=?|>{1,2}=?|\->|:{1,2}|={1,2}|\^|~|%|&{1,2}|\|?\||\?|\*|\/|\b(and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/}),n.languages.insertBefore("cpp","keyword",{"class-name":{pattern:/(class\s+)[a-z0-9_]+/i,lookbehind:!0}}),n.languages.java=n.languages.extend("clike",{keyword:/\b(abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\b/,number:/\b0b[01]+\b|\b0x[\da-f]*\.?[\da-fp\-]+\b|\b\d*\.?\d+(?:e[+-]?\d+)?[df]?\b/i,operator:{pattern:/(^|[^.])(?:\+[+=]?|-[-=]?|!=?|<>?>?=?|==?|&[&=]?|\|[|=]?|\*=?|\/=?|%=?|\^=?|[?:~])/m,lookbehind:!0}}),n.languages.php=n.languages.extend("clike",{keyword:/\b(and|or|xor|array|as|break|case|cfunction|class|const|continue|declare|default|die|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|for|foreach|function|include|include_once|global|if|new|return|static|switch|use|require|require_once|var|while|abstract|interface|public|implements|private|protected|parent|throw|null|echo|print|trait|namespace|final|yield|goto|instanceof|finally|try|catch)\b/i,constant:/\b[A-Z0-9_]{2,}\b/,comment:{pattern:/(^|[^\\])(?:\/\*[\w\W]*?\*\/|\/\/.*)/,lookbehind:!0}}),n.languages.insertBefore("php","class-name",{"shell-comment":{pattern:/(^|[^\\])#.*/,lookbehind:!0,alias:"comment"}}),n.languages.insertBefore("php","keyword",{delimiter:/\?>|<\?(?:php)?/i,variable:/\$\w+\b/i,"package":{pattern:/(\\|namespace\s+|use\s+)[\w\\]+/,lookbehind:!0,inside:{punctuation:/\\/}}}),n.languages.insertBefore("php","operator",{property:{pattern:/(->)[\w]+/,lookbehind:!0}}),n.languages.markup&&(n.hooks.add("before-highlight",function(e){"php"===e.language&&(e.tokenStack=[],e.backupCode=e.code,e.code=e.code.replace(/(?:<\?php|<\?)[\w\W]*?(?:\?>)/gi,function(t){return e.tokenStack.push(t),"{{{PHP"+e.tokenStack.length+"}}}"}))}),n.hooks.add("before-insert",function(e){"php"===e.language&&(e.code=e.backupCode,delete e.backupCode)}),n.hooks.add("after-highlight",function(e){if("php"===e.language){for(var t,r=0;t=e.tokenStack[r];r++)e.highlightedCode=e.highlightedCode.replace("{{{PHP"+(r+1)+"}}}",n.highlight(t,e.grammar,"php").replace(/\$/g,"$$$$"));e.element.innerHTML=e.highlightedCode}}),n.hooks.add("wrap",function(e){"php"===e.language&&"markup"===e.type&&(e.content=e.content.replace(/(\{\{\{PHP[0-9]+\}\}\})/g,'$1'))}),n.languages.insertBefore("php","comment",{markup:{pattern:/<[^?]\/?(.*?)>/,inside:n.languages.markup},php:/\{\{\{PHP[0-9]+\}\}\}/})),n.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},string:/"""[\s\S]+?"""|'''[\s\S]+?'''|("|')(?:\\?.)*?\1/,"function":{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_][a-zA-Z0-9_]*(?=\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)[a-z0-9_]+/i,lookbehind:!0},keyword:/\b(?:as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|pass|print|raise|return|try|while|with|yield)\b/,"boolean":/\b(?:True|False)\b/,number:/\b-?(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]|\b(?:or|and|not)\b/,punctuation:/[{}[\];(),.:]/},function(e){e.languages.ruby=e.languages.extend("clike",{comment:/#(?!\{[^\r\n]*?\}).*/,keyword:/\b(alias|and|BEGIN|begin|break|case|class|def|define_method|defined|do|each|else|elsif|END|end|ensure|false|for|if|in|module|new|next|nil|not|or|raise|redo|require|rescue|retry|return|self|super|then|throw|true|undef|unless|until|when|while|yield)\b/});var t={pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"tag"},rest:e.util.clone(e.languages.ruby)}};e.languages.insertBefore("ruby","keyword",{regex:[{pattern:/%r([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\1[gim]{0,3}/,inside:{interpolation:t}},{pattern:/%r\((?:[^()\\]|\\[\s\S])*\)[gim]{0,3}/,inside:{interpolation:t}},{pattern:/%r\{(?:[^#{}\\]|#(?:\{[^}]+\})?|\\[\s\S])*\}[gim]{0,3}/,inside:{interpolation:t}},{pattern:/%r\[(?:[^\[\]\\]|\\[\s\S])*\][gim]{0,3}/,inside:{interpolation:t}},{pattern:/%r<(?:[^<>\\]|\\[\s\S])*>[gim]{0,3}/,inside:{interpolation:t}},{pattern:/(^|[^\/])\/(?!\/)(\[.+?]|\\.|[^\/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0}],variable:/[@$]+[a-zA-Z_][a-zA-Z_0-9]*(?:[?!]|\b)/,symbol:/:[a-zA-Z_][a-zA-Z_0-9]*(?:[?!]|\b)/}),e.languages.insertBefore("ruby","number",{builtin:/\b(Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Stat|File|Fixnum|Fload|Hash|Integer|IO|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|String|Struct|TMS|Symbol|ThreadGroup|Thread|Time|TrueClass)\b/,constant:/\b[A-Z][a-zA-Z_0-9]*(?:[?!]|\b)/}),e.languages.ruby.string=[{pattern:/%[qQiIwWxs]?([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\1/,inside:{interpolation:t}},{pattern:/%[qQiIwWxs]?\((?:[^()\\]|\\[\s\S])*\)/,inside:{interpolation:t}},{pattern:/%[qQiIwWxs]?\{(?:[^#{}\\]|#(?:\{[^}]+\})?|\\[\s\S])*\}/,inside:{interpolation:t}},{pattern:/%[qQiIwWxs]?\[(?:[^\[\]\\]|\\[\s\S])*\]/,inside:{interpolation:t}},{pattern:/%[qQiIwWxs]?<(?:[^<>\\]|\\[\s\S])*>/,inside:{interpolation:t}},{pattern:/("|')(#\{[^}]+\}|\\(?:\r?\n|\r)|\\?.)*?\1/,inside:{interpolation:t}}]}(n),n}),r("tinymce/codesampleplugin/Utils",[],function(){function e(e){return e&&"PRE"==e.nodeName&&-1!==e.className.indexOf("language-")}function t(e){return function(t,n){return e(n)}}return{isCodeSample:e,trimArg:t}}),r("tinymce/codesampleplugin/Dialog",["tinymce/dom/DOMUtils","tinymce/codesampleplugin/Utils","tinymce/codesampleplugin/Prism"],function(e,t,n){function r(e,t,r){e.undoManager.transact(function(){var o=i(e);r=s.encode(r),o?(e.dom.setAttrib(o,"class","language-"+t),o.innerHTML=r,n.highlightElement(o),e.selection.select(o)):(e.insertContent('

'+r+"
"),e.selection.select(e.$("#__new").removeAttr("id")[0]))})}function i(e){var n=e.selection.getNode();return t.isCodeSample(n)?n:null}function o(e){var t=i(e);return t?t.textContent:""}function a(e){var t,n=i(e);return n?(t=n.className.match(/language-(\w+)/),t?t[1]:""):""}var s=e.DOM,l=[{text:"HTML/XML",value:"markup"},{text:"JavaScript",value:"javascript"},{text:"CSS",value:"css"},{text:"PHP",value:"php"},{text:"Ruby",value:"ruby"},{text:"Python",value:"python"},{text:"Java",value:"java"},{text:"C",value:"c"},{text:"C#",value:"csharp"},{text:"C++",value:"cpp"}];return{open:function(e){e.windowManager.open({title:"Insert/Edit code sample",minWidth:Math.min(s.getViewPort().w,800),minHeight:Math.min(s.getViewPort().h,650),layout:"fit",body:[{type:"listbox",name:"language",label:"Language",maxWidth:200,value:a(e),values:l},{type:"textbox",name:"code",multiline:!0,spellcheck:!1,ariaLabel:"Code view",flex:1,style:"direction: ltr; text-align: left",classes:"monospace",value:o(e)}],onSubmit:function(t){r(e,t.data.language,t.data.code)}})}}}),r("tinymce/codesampleplugin/Plugin",["tinymce/Env","tinymce/PluginManager","tinymce/codesampleplugin/Prism","tinymce/codesampleplugin/Dialog","tinymce/codesampleplugin/Utils"],function(e,t,n,r,i){var o,a=i.trimArg;t.add("codesample",function(t,s){function l(){var e;o||(o=!0,e=t.dom.create("link",{rel:"stylesheet",href:s+"/css/prism.css"}),t.getDoc().getElementsByTagName("head")[0].appendChild(e))}var c=t.$;e.ceFalse&&(t.on("PreProcess",function(e){c("pre[contenteditable=false]",e.node).filter(a(i.isCodeSample)).each(function(e,t){var n=c(t),r=t.textContent;n.attr("class",c.trim(n.attr("class"))),n.removeAttr("contentEditable"),n.empty().append(c("").each(function(){this.textContent=r}))})}),t.on("SetContent",function(){var e=c("pre").filter(a(i.isCodeSample)).filter(function(e,t){return"false"!==t.contentEditable});e.length&&t.undoManager.transact(function(){e.each(function(e,r){c(r).find("br").each(function(e,n){n.parentNode.replaceChild(t.getDoc().createTextNode("\n"),n)}),r.contentEditable=!1,r.innerHTML=t.dom.encode(r.textContent),n.highlightElement(r),r.className=c.trim(r.className)})})}),t.addCommand("codesample",function(){r.open(t)}),t.addButton("codesample",{cmd:"codesample",title:"Insert/Edit code sample"}),t.on("init",l))})}),o(["tinymce/codesampleplugin/Prism","tinymce/codesampleplugin/Utils","tinymce/codesampleplugin/Dialog","tinymce/codesampleplugin/Plugin"])}(this); \ No newline at end of file diff --git a/src/plugin/richText/tinymce/plugins/colorpicker/plugin.min.js b/src/plugin/richText/tinymce/plugins/colorpicker/plugin.min.js new file mode 100644 index 000000000..b56b88f4c --- /dev/null +++ b/src/plugin/richText/tinymce/plugins/colorpicker/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("colorpicker",function(e){function t(t,n){function r(e){var t=new tinymce.util.Color(e),n=t.toRgb();o.fromJSON({r:n.r,g:n.g,b:n.b,hex:t.toHex().substr(1)}),i(t.toHex())}function i(e){o.find("#preview")[0].getEl().style.background=e}var o=e.windowManager.open({title:"Color",items:{type:"container",layout:"flex",direction:"row",align:"stretch",padding:5,spacing:10,items:[{type:"colorpicker",value:n,onchange:function(){var e=this.rgb();o&&(o.find("#r").value(e.r),o.find("#g").value(e.g),o.find("#b").value(e.b),o.find("#hex").value(this.value().substr(1)),i(this.value()))}},{type:"form",padding:0,labelGap:5,defaults:{type:"textbox",size:7,value:"0",flex:1,spellcheck:!1,onchange:function(){var e,t,n=o.find("colorpicker")[0];return e=this.name(),t=this.value(),"hex"==e?(t="#"+t,r(t),void n.value(t)):(t={r:o.find("#r").value(),g:o.find("#g").value(),b:o.find("#b").value()},n.value(t),void r(t))}},items:[{name:"r",label:"R",autofocus:1},{name:"g",label:"G"},{name:"b",label:"B"},{name:"hex",label:"#",value:"000000"},{name:"preview",type:"container",border:1}]}]},onSubmit:function(){t("#"+this.toJSON().hex)}});r(n)}e.settings.color_picker_callback||(e.settings.color_picker_callback=t)}); \ No newline at end of file diff --git a/src/plugin/richText/tinymce/plugins/contextmenu/plugin.min.js b/src/plugin/richText/tinymce/plugins/contextmenu/plugin.min.js new file mode 100644 index 000000000..968740802 --- /dev/null +++ b/src/plugin/richText/tinymce/plugins/contextmenu/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("contextmenu",function(e){var t,n=e.settings.contextmenu_never_use_native;e.on("contextmenu",function(r){var i,o=e.getDoc();if(!r.ctrlKey||n){if(r.preventDefault(),tinymce.Env.mac&&tinymce.Env.webkit&&2==r.button&&o.caretRangeFromPoint&&e.selection.setRng(o.caretRangeFromPoint(r.x,r.y)),i=e.settings.contextmenu||"link image inserttable | cell row column deletetable",t)t.show();else{var a=[];tinymce.each(i.split(/[ ,]/),function(t){var n=e.menuItems[t];"|"==t&&(n={text:t}),n&&(n.shortcut="",a.push(n))});for(var s=0;sKx}s1_F$4FCWDA^8LW0018VEC2ui01^Na000Hw;3tYzX_jM3Qpv$_M?zI9i5=0S zX-{-uv=l3%&P0s%m9Ox_a(m_c|u z01g3U0`Wll5)poVdma=N8y<3f0Sf~hXmTC}2oxMW4FdxUj+z4<0}lrX2nP=qkDRIt z9Ge*(qzMrj3jrIOjvI{`5eWzt3`G_T8yChG8w(a19SkK12@M(+799Zr9n=~PzBCmA z5)BU-)YKUd4H5!D9|!^o9kWIe9SH(WDHRk92}DZ?3})2$P@$55g90f0N)ZA8JID5J Aw*UYD literal 0 HcmV?d00001 diff --git a/src/plugin/richText/tinymce/plugins/emoticons/img/smiley-cry.gif b/src/plugin/richText/tinymce/plugins/emoticons/img/smiley-cry.gif new file mode 100644 index 0000000000000000000000000000000000000000..74d897a4f6d22e814e2b054e98b8a75fb464b4be GIT binary patch literal 329 zcmV-P0k-}}Nk%w1VG;lm0Mr-&E)xPSit@9T3%;vR+|V+?t0A(pllJjXrMl7n=_A_a za^B+Su$LjvyC3@TIQZNZa##w=!k(SO^P#bO*w(eU#;{U83XFCU_V)J5wrb+;g2vkN z#>U24qVoOvY5)KLA^8LW0018VEC2ui01^Na000HX;3tY$X_jM3QUfCh%s^o(nF++< zc?Th6v=oL>*by8K!mhvwelUXuuW&&U9iGO3hM@>Njw{l^#0q9mWpcefdI;O$;efnY zkd~@r-o$*74FCWI1%d((4+jDz0va0>69^fI6%`W{8w!gU1pyL>prH>E0R<%k6Aq%H z4ij+^9TEwM5P}eh2@)L<~6+>@EpxfA0YrcPNsSu literal 0 HcmV?d00001 diff --git a/src/plugin/richText/tinymce/plugins/emoticons/img/smiley-embarassed.gif b/src/plugin/richText/tinymce/plugins/emoticons/img/smiley-embarassed.gif new file mode 100644 index 0000000000000000000000000000000000000000..963a96b8a7593b1d8bcbab073abe5ee4e539dbf6 GIT binary patch literal 331 zcmV-R0kr-{Nk%w1VG;lm0MrryDh>j~yq&6%75dW~z^P39(NxsGDE{UkxtkIEq(S-a zRKlwv+S=Lr?>hbYY~sQ?c3T&ZcN_Nh_EU3s(>Io6B&>WW`@bsw**)Ocy1bht z{*G6|uwwqUQ2+n{A^8LW0018VEC2ui01^Na000HZ;3tYwX_jM3YQ!c88=*-m*&&bO zILd=`w3KAC;8hxpif*w9ek6oqV-Z0L77fROK$BSR@5BAv-%C>6y>>#+D4e#&nz^qMDItlpp zTG728+|V&?R13PIEBW(C`uh6d*t-1sZ^XQv;oDD}iYLOV7uVO;{`xl4#4tJ{0;h@! z>)kdc3IhA?Hvj+tA^8La0018VEC2ui01^Na06+!P;3tYuX_ljS7!u|-O)I}TzP1q%xT4HOFwMJaO;2ml)!00$)141pU08x3594IX?4 o5YuAA8yXz~76K1c;3^jg77WP185Rf^u}23N0sR5^q(T4yJ1sVN5dZ)H literal 0 HcmV?d00001 diff --git a/src/plugin/richText/tinymce/plugins/emoticons/img/smiley-frown.gif b/src/plugin/richText/tinymce/plugins/emoticons/img/smiley-frown.gif new file mode 100644 index 0000000000000000000000000000000000000000..716f55e161bfebb1c3d34f0b0f40c177fc82c30b GIT binary patch literal 340 zcmV-a0jvH;Nk%w1VG;lm0MroxK_>;q#>Sw62=mns-On=0wransPVevT^YK{Dy(0YY zH)vE6x0?;Wqb>gZas1^OT0si>`ugD5y87}*#H$s=yq(wA*8cf7{`y+(+9J7|9QfT7 z`ROHiU=Y&6FaQ7mA^8LW0018VEC2ui01^Na000Hi;3tYvX_jM3N`@u~nju9hSuh^r zIEcp-wA7(NL0~2d#RP+(G!CPPA>o*KJjv_CkucCA5=K?AfF#RG2V*8BU@jL304|4P z2;PGRF@bj$et;Jf2pR_mVsIA<85|n}kQ*Bq42Ovqj*yy>6P0=h3X&9Z01yyk~2N4w%7#RW^55W%`0vQ+-6(y_*2pqz~90*;x9}yM}%$UI(7t#$D mK_3Se1{4HKM+6iG7EmeH6$V631{L5n)#CyC0qx-*Apkoyg?w!Q literal 0 HcmV?d00001 diff --git a/src/plugin/richText/tinymce/plugins/emoticons/img/smiley-innocent.gif b/src/plugin/richText/tinymce/plugins/emoticons/img/smiley-innocent.gif new file mode 100644 index 0000000000000000000000000000000000000000..334d49e0e60f2997c9ba24071764f95d9e08a5cc GIT binary patch literal 336 zcmV-W0k8f?Nk%w1VG;lm0MrryI4TI-%dP0m5~*+Y`T~ z7Rth){q{I_X%*S48uRZ|(b3V&wIKTX`u+WJzo<^$#wuY;3W|Cf{O29IkTAcaE&lpe z+P*^H)-tknA^-pYA^8LW0018VEC2ui01^Na000He;3tYwX_n)75QgVvNQ`6#5gcMm zEEG~blgXokptKAJgCU?%JT?yos!R6cPtcQWh2siHlNI2L}ifQhgX02^InZ2?-ktkqVRyZJY^Trk|lv zovp437?1~d46O)?2(1i+2NDYk8<+_Kil!K!3njA^!I#dL8x<729}*B65mC=m5gHH@ iDi9P3f*VjB3KS4HDb_qqRul{0DIT=Nk%w1VG;lm0Mrx!QauaC#>Vb6G=_5=^YB^9wrc376Sb5I-qJGf@9vZ# z5WlKU(!eVB+7tfnDXp0zyB`?BZ5IChalob*`uh6d*t+@dKGHcU+L|83yq*5~IoH?L zy`?Gp<{bX|SpWb4A^8LW0018VEC2ui01^Na000Hg;3tYyX_jM3R?Bl7&r(q;SsVx< zNd$5fv{ZsKA$SlL3&KN~a1tZRf*~1Ltkx9~2uL3&z-yb0WJDRY082|tP literal 0 HcmV?d00001 diff --git a/src/plugin/richText/tinymce/plugins/emoticons/img/smiley-laughing.gif b/src/plugin/richText/tinymce/plugins/emoticons/img/smiley-laughing.gif new file mode 100644 index 0000000000000000000000000000000000000000..82c5b182e61d32bd394acae551eff180f1eebd26 GIT binary patch literal 343 zcmV-d0jT~*Nk%w1VG;lm0Q4UK!lp8=s;1-69HWK?p_PpF=Pd8~Ygtcnp*fHAL z**;z>w3iC}`fmL6IkKB1N;3zEa}&zKpsu1;_V)HocR5-{J~BcYvE`YXhBnc@CfU=! za(Ec zG>66zv=rqr;2j)}gKqE$ekcSD?}0=WLB?AWp85)qALd+P=4)6X4oXy{bw2>K^d$ z@6ERvva+(4ib~41YUkTEn1&#?rzrOHT>1I=Y*h`+%*@WtPUPg|!@EEI_d5LgZ>^Og z-qyBKJqy*wF8}}lA^8La0018VEC2ui01^Na06+!6;3tYxX_lj?7+U61R3gAaEg8x< zT>%mSfCwURnWQF&g=Q0ZxH1ulW`QtH0>O!5%iT_X0VBy_@EkOngU8?ye~=H!t21{= z9@Uj3a_UbE88~kh5Eq7rh!7QSBn1c?0|Off1&k^`5*QE<4-gmSR<4C>Dj%C>6W(lWoQPVevT^YB^Fy&h6M z4YZgH{O~qtR1(Ci8T;lQ`uh6d*t-7xar*K{#Jrulo-Wtd*44u?{`oh#n;gQXGXDEo z_}UUC3IeK%0ssI2A^8La0018VEC2ui01^Na06+!R;3tYuX_ljSEE482&%+G^XK%|f zLKbCc4u{4-u|QG~LqamSTo?@JM3OKZAr!|Z2IzP@fY`=CIg$vA3qm46TowfLCt29I z6pDKuvnf~)83+sm9yW#?9s>^(89F=~2?!W44-6Ox2^vNza}fp^9v&G65pp936%Gg+ z6HpTy2o4oGoh+>l3Q)KVQwybl2oo*<4a3D469|nfEii|MH4`}p1_cZp0ssj%2>=2d q41Na?)CpS;4gvxWVpZcR76uLludD?Q1{SnP2NnVU0rZ&)0RTIit8@_n literal 0 HcmV?d00001 diff --git a/src/plugin/richText/tinymce/plugins/emoticons/img/smiley-surprised.gif b/src/plugin/richText/tinymce/plugins/emoticons/img/smiley-surprised.gif new file mode 100644 index 0000000000000000000000000000000000000000..0cc9bb71cca4cdeafbb248ce7e07c3708c1cbd64 GIT binary patch literal 338 zcmV-Y0j>T=Nk%w1VG;lm0Q4UK`{WwN#>SnDDC*4*{OcpiwransPVevTQacIr@mkQp zCf(06s)_=>r7UYx48o@u`uh6d*t-7rH~ji<`P&oj;5Wp)o!8ga`SV6TA_BIW5#ZWV z{`*)c32kA}f=futY?#YE7kxGD|7L}4&OEDw$hkm+~<00QS>F_H?J#bz?uEHnl42f5(9 z5O)`6Q9V2o5;YVLUK)Y`7!Nr+4GMq?85s%^2?`BGDRU798Vn2?1`%>22R{iO0u>bk z9tlA?nk*O<3zHJH6&Mp5qALj)E(mxM!Y&vII4dm@1Ov{`f*8pL3xPEVUI>D>1_uxa kNm?`6VH{N6Di;P13m6<67z+;u7qCYM7XkVK^`jvGJD~P?KL7v# literal 0 HcmV?d00001 diff --git a/src/plugin/richText/tinymce/plugins/emoticons/img/smiley-tongue-out.gif b/src/plugin/richText/tinymce/plugins/emoticons/img/smiley-tongue-out.gif new file mode 100644 index 0000000000000000000000000000000000000000..2075dc16058f1f17912167675ce5cfb9986fc71d GIT binary patch literal 328 zcmV-O0k{4~Nk%w1VG;lm0Mrx!CJF+^#>SU@3-{U*rx+Q^wrc$ABfqLn@9*x?z8(4X zSW-O=@){bmmI~g|GQXoP);cvj3|f1M8e@{G*!tYaiCEujj1NGxRN#6#tiCETo+{x{Hkzt z5k-kPvcD=V2nbmjCgL6k{uF&2nP-t0s;w<385Nx2oxDb z9T5Pp7qJl?3Kkh9oe2sCr5F$p7zPSlsUH*@54w*83=9Or4;w)r2pcU95(FL|1Th;< aDaRQH4;Tal7#Y$v#?=Au0pHUfApkpvZg^t= literal 0 HcmV?d00001 diff --git a/src/plugin/richText/tinymce/plugins/emoticons/img/smiley-undecided.gif b/src/plugin/richText/tinymce/plugins/emoticons/img/smiley-undecided.gif new file mode 100644 index 0000000000000000000000000000000000000000..bef7e257303f8243c89787e7a7f9955dd1f112e2 GIT binary patch literal 337 zcmV-X0j~Z>Nk%w1VG;lm0MroxDi#99#>R?y8~4}{%C>6#>?OadPVevTr-=vi@LATn z4rERY-qJF+n+?CCE&B3D{{3Shh?>WT0o%`b%*Voqm`dL;(4F35y zc485^n;g!+Bme*aA^8LW0018VEC2ui01^Na000Hf;3tYvX_jM3N=AnuogqakNi<9X zK?&0kwA8^tNn{?C$|IAYI1ZzT!2>}iuMddFK#NEkRl!7%6brJAnUs;)XcnA}TNBSP zxQ9;SvEfwYeSaGd2^|LqU~(QF1qBxr3Ii7x84ZVt8wCTKoSYAqc?p`G2onnpk`IOl z1`HLGj}riN2p1K12N4z&8IBDc6tEWs859;JtRB6>lf+xO9}yT19toMv8wnl`7(pKg j7zPv!OGgY81{hE&(iR3pP6ig;HPPS!_yOwPA0Yrc)=Yf3 literal 0 HcmV?d00001 diff --git a/src/plugin/richText/tinymce/plugins/emoticons/img/smiley-wink.gif b/src/plugin/richText/tinymce/plugins/emoticons/img/smiley-wink.gif new file mode 100644 index 0000000000000000000000000000000000000000..0631c7616ec8624ddeee02b633326f697ee72f80 GIT binary patch literal 350 zcmV-k0ipg!Nk%w1VG;lm0Q4UK(ZVUl#>Sn03F^-g-qAA3wransPV?|t@9*x%vmQ`7 z4E*pcw3rOOq%3t@4*K#({N^40{c-yG`rz2Q!KfI-yq*61HrBop*VoqW<}&{JS@_x# zwwfF$4Fdh~IsgCwA^8La0018VEC2ui01^Na06+!X;3tYwX_ljiFp=e23$zWxW@`*G zN?2ty6iUNT!AMdPLn89IbS7WCB_mWF$+hzY-{PWkp(?(Xf;zbH~P z3jOdj?W+^YwrakfE8fyG&5jTBz!3WS`fgM_;MltQ+c}4GO8)(E`S3`@yq&d~5!ct& z)v79NObo)O7XSbNA^8LW0018VEC2ui01^Na000He;3tYwX_jM3QifI(nn6h_*=Wyk zUB{y}v=qYOIUF#R3dZPhAVv~H;(|a2yN_5FH&J0|$eJ3kw4gj1Y?v5d#>LMV12^6BYy$1)ZKA zga!|m2?POz0R)f>4+aPl8KD{gz`+G_9vLMFQU?RU!8uyH9}*i52|cC+7S0YEK_3Vk i1|APfM-Ltb8&4_H83sg61{vHn(cc000qNZzApkp'}),e+=""}),e+=""}var r=[["cool","cry","embarassed","foot-in-mouth"],["frown","innocent","kiss","laughing"],["money-mouth","sealed","smile","surprised"],["tongue-out","undecided","wink","yell"]];e.addButton("emoticons",{type:"panelbutton",panel:{role:"application",autohide:!0,html:n,onclick:function(t){var n=e.dom.getParent(t.target,"a");n&&(e.insertContent(''+n.getAttribute('),this.hide())}},tooltip:"Emoticons"})}); \ No newline at end of file diff --git a/src/plugin/richText/tinymce/plugins/example/dialog.html b/src/plugin/richText/tinymce/plugins/example/dialog.html new file mode 100644 index 000000000..565f06f5e --- /dev/null +++ b/src/plugin/richText/tinymce/plugins/example/dialog.html @@ -0,0 +1,8 @@ + + + +

Custom dialog

+ Input some text: + + + \ No newline at end of file diff --git a/src/plugin/richText/tinymce/plugins/example/plugin.min.js b/src/plugin/richText/tinymce/plugins/example/plugin.min.js new file mode 100644 index 000000000..b47d90f6b --- /dev/null +++ b/src/plugin/richText/tinymce/plugins/example/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("example",function(e,t){e.addButton("example",{text:"My button",icon:!1,onclick:function(){e.windowManager.open({title:"Example plugin",body:[{type:"textbox",name:"title",label:"Title"}],onsubmit:function(t){e.insertContent("Title: "+t.data.title)}})}}),e.addMenuItem("example",{text:"Example plugin",context:"tools",onclick:function(){e.windowManager.open({title:"TinyMCE site",url:t+"/dialog.html",width:600,height:400,buttons:[{text:"Insert",onclick:function(){var t=e.windowManager.getWindows()[0];e.insertContent(t.getContentWindow().document.getElementById("content").value),t.close()}},{text:"Close",onclick:"close"}]})}})}); \ No newline at end of file diff --git a/src/plugin/richText/tinymce/plugins/example_dependency/plugin.min.js b/src/plugin/richText/tinymce/plugins/example_dependency/plugin.min.js new file mode 100644 index 000000000..e61bf473a --- /dev/null +++ b/src/plugin/richText/tinymce/plugins/example_dependency/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("example_dependency",function(){},["example"]); \ No newline at end of file diff --git a/src/plugin/richText/tinymce/plugins/fullpage/plugin.min.js b/src/plugin/richText/tinymce/plugins/fullpage/plugin.min.js new file mode 100644 index 000000000..6d06748c0 --- /dev/null +++ b/src/plugin/richText/tinymce/plugins/fullpage/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("fullpage",function(e){function t(){var t=n();e.windowManager.open({title:"Document properties",data:t,defaults:{type:"textbox",size:40},body:[{name:"title",label:"Title"},{name:"keywords",label:"Keywords"},{name:"description",label:"Description"},{name:"robots",label:"Robots"},{name:"author",label:"Author"},{name:"docencoding",label:"Encoding"}],onSubmit:function(e){r(tinymce.extend(t,e.data))}})}function n(){function t(e,t){var n=e.attr(t);return n||""}var n,r,o=i(),a={};return a.fontface=e.getParam("fullpage_default_fontface",""),a.fontsize=e.getParam("fullpage_default_fontsize",""),n=o.firstChild,7==n.type&&(a.xml_pi=!0,r=/encoding="([^"]+)"/.exec(n.value),r&&(a.docencoding=r[1])),n=o.getAll("#doctype")[0],n&&(a.doctype=""),n=o.getAll("title")[0],n&&n.firstChild&&(a.title=n.firstChild.value),u(o.getAll("meta"),function(e){var t,n=e.attr("name"),r=e.attr("http-equiv");n?a[n.toLowerCase()]=e.attr("content"):"Content-Type"==r&&(t=/charset\s*=\s*(.*)\s*/gi.exec(e.attr("content")),t&&(a.docencoding=t[1]))}),n=o.getAll("html")[0],n&&(a.langcode=t(n,"lang")||t(n,"xml:lang")),a.stylesheets=[],tinymce.each(o.getAll("link"),function(e){"stylesheet"==e.attr("rel")&&a.stylesheets.push(e.attr("href"))}),n=o.getAll("body")[0],n&&(a.langdir=t(n,"dir"),a.style=t(n,"style"),a.visited_color=t(n,"vlink"),a.link_color=t(n,"link"),a.active_color=t(n,"alink")),a}function r(t){function n(e,t,n){e.attr(t,n?n:void 0)}function r(e){a.firstChild?a.insert(e,a.firstChild):a.append(e)}var o,a,s,c,f,h=e.dom;o=i(),a=o.getAll("head")[0],a||(c=o.getAll("html")[0],a=new d("head",1),c.firstChild?c.insert(a,c.firstChild,!0):c.append(a)),c=o.firstChild,t.xml_pi?(f='version="1.0"',t.docencoding&&(f+=' encoding="'+t.docencoding+'"'),7!=c.type&&(c=new d("xml",7),o.insert(c,o.firstChild,!0)),c.value=f):c&&7==c.type&&c.remove(),c=o.getAll("#doctype")[0],t.doctype?(c||(c=new d("#doctype",10),t.xml_pi?o.insert(c,o.firstChild):r(c)),c.value=t.doctype.substring(9,t.doctype.length-1)):c&&c.remove(),c=null,u(o.getAll("meta"),function(e){"Content-Type"==e.attr("http-equiv")&&(c=e)}),t.docencoding?(c||(c=new d("meta",1),c.attr("http-equiv","Content-Type"),c.shortEnded=!0,r(c)),c.attr("content","text/html; charset="+t.docencoding)):c&&c.remove(),c=o.getAll("title")[0],t.title?(c?c.empty():(c=new d("title",1),r(c)),c.append(new d("#text",3)).value=t.title):c&&c.remove(),u("keywords,description,author,copyright,robots".split(","),function(e){var n,i,a=o.getAll("meta"),s=t[e];for(n=0;n"))}function i(){return new tinymce.html.DomParser({validate:!1,root_name:"#document"}).parse(l)}function o(t){function n(e){return e.replace(/<\/?[A-Z]+/g,function(e){return e.toLowerCase()})}var r,o,s,d,f=t.content,h="",m=e.dom;if(!t.selection&&!("raw"==t.format&&l||t.source_view&&e.getParam("fullpage_hide_in_source_view"))){0!==f.length||t.source_view||(f=tinymce.trim(l)+"\n"+tinymce.trim(f)+"\n"+tinymce.trim(c)),f=f.replace(/<(\/?)BODY/gi,"<$1body"),r=f.indexOf("",r),l=n(f.substring(0,r+1)),o=f.indexOf("\n"),s=i(),u(s.getAll("style"),function(e){e.firstChild&&(h+=e.firstChild.value)}),d=s.getAll("body")[0],d&&m.setAttribs(e.getBody(),{style:d.attr("style")||"",dir:d.attr("dir")||"",vLink:d.attr("vlink")||"",link:d.attr("link")||"",aLink:d.attr("alink")||""}),m.remove("fullpage_styles");var p=e.getDoc().getElementsByTagName("head")[0];h&&(m.add(p,"style",{id:"fullpage_styles"},h),d=m.get("fullpage_styles"),d.styleSheet&&(d.styleSheet.cssText=h));var g={};tinymce.each(p.getElementsByTagName("link"),function(e){"stylesheet"==e.rel&&e.getAttribute("data-mce-fullpage")&&(g[e.href]=e)}),tinymce.each(s.getAll("link"),function(e){var t=e.attr("href");g[t]||"stylesheet"!=e.attr("rel")||m.add(p,"link",{rel:"stylesheet",text:"text/css",href:t,"data-mce-fullpage":"1"}),delete g[t]}),tinymce.each(g,function(e){e.parentNode.removeChild(e)})}}function a(){var t,n="",r="";return e.getParam("fullpage_default_xml_pi")&&(n+='\n'),n+=e.getParam("fullpage_default_doctype",""),n+="\n\n\n",(t=e.getParam("fullpage_default_title"))&&(n+=""+t+"\n"),(t=e.getParam("fullpage_default_encoding"))&&(n+='\n'),(t=e.getParam("fullpage_default_font_family"))&&(r+="font-family: "+t+";"),(t=e.getParam("fullpage_default_font_size"))&&(r+="font-size: "+t+";"),(t=e.getParam("fullpage_default_text_color"))&&(r+="color: "+t+";"),n+="\n\n"}function s(t){t.selection||t.source_view&&e.getParam("fullpage_hide_in_source_view")||(t.content=tinymce.trim(l)+"\n"+tinymce.trim(t.content)+"\n"+tinymce.trim(c))}var l,c,u=tinymce.each,d=tinymce.html.Node;e.addCommand("mceFullPageProperties",t),e.addButton("fullpage",{title:"Document properties",cmd:"mceFullPageProperties"}),e.addMenuItem("fullpage",{text:"Document properties",cmd:"mceFullPageProperties",context:"file"}),e.on("BeforeSetContent",o),e.on("GetContent",s)}); \ No newline at end of file diff --git a/src/plugin/richText/tinymce/plugins/fullscreen/plugin.min.js b/src/plugin/richText/tinymce/plugins/fullscreen/plugin.min.js new file mode 100644 index 000000000..e7304f963 --- /dev/null +++ b/src/plugin/richText/tinymce/plugins/fullscreen/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("fullscreen",function(e){function t(){var e,t,n=window,r=document,i=r.body;return i.offsetWidth&&(e=i.offsetWidth,t=i.offsetHeight),n.innerWidth&&n.innerHeight&&(e=n.innerWidth,t=n.innerHeight),{w:e,h:t}}function n(){var e=tinymce.DOM.getViewPort();return{x:e.x,y:e.y}}function r(e){scrollTo(e.x,e.y)}function i(){function i(){f.setStyle(p,"height",t().h-(m.clientHeight-p.clientHeight))}var h,m,p,g,v=document.body,y=document.documentElement;d=!d,m=e.getContainer(),h=m.style,p=e.getContentAreaContainer().firstChild,g=p.style,d?(u=n(),o=g.width,a=g.height,g.width=g.height="100%",l=h.width,c=h.height,h.width=h.height="",f.addClass(v,"mce-fullscreen"),f.addClass(y,"mce-fullscreen"),f.addClass(m,"mce-fullscreen"),f.bind(window,"resize",i),i(),s=i):(g.width=o,g.height=a,l&&(h.width=l),c&&(h.height=c),f.removeClass(v,"mce-fullscreen"),f.removeClass(y,"mce-fullscreen"),f.removeClass(m,"mce-fullscreen"),f.unbind(window,"resize",s),r(u)),e.fire("FullscreenStateChanged",{state:d})}var o,a,s,l,c,u,d=!1,f=tinymce.DOM;return e.settings.inline?void 0:(e.on("init",function(){e.addShortcut("Meta+Alt+F","",i)}),e.on("remove",function(){s&&f.unbind(window,"resize",s)}),e.addCommand("mceFullScreen",i),e.addMenuItem("fullscreen",{text:"Fullscreen",shortcut:"Meta+Alt+F",selectable:!0,onClick:i,onPostRender:function(){var t=this;e.on("FullscreenStateChanged",function(e){t.active(e.state)})},context:"view"}),e.addButton("fullscreen",{tooltip:"Fullscreen",shortcut:"Meta+Alt+F",onClick:i,onPostRender:function(){var t=this;e.on("FullscreenStateChanged",function(e){t.active(e.state)})}}),{isFullscreen:function(){return d}})}); \ No newline at end of file diff --git a/src/plugin/richText/tinymce/plugins/hr/plugin.min.js b/src/plugin/richText/tinymce/plugins/hr/plugin.min.js new file mode 100644 index 000000000..ca36c9275 --- /dev/null +++ b/src/plugin/richText/tinymce/plugins/hr/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("hr",function(e){e.addCommand("InsertHorizontalRule",function(){e.execCommand("mceInsertContent",!1,"
")}),e.addButton("hr",{icon:"hr",tooltip:"Horizontal line",cmd:"InsertHorizontalRule"}),e.addMenuItem("hr",{icon:"hr",text:"Horizontal line",cmd:"InsertHorizontalRule",context:"insert"})}); \ No newline at end of file diff --git a/src/plugin/richText/tinymce/plugins/image/plugin.min.js b/src/plugin/richText/tinymce/plugins/image/plugin.min.js new file mode 100644 index 000000000..5d620c7b3 --- /dev/null +++ b/src/plugin/richText/tinymce/plugins/image/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("image",function(e){function t(e,t){function n(e,n){r.parentNode&&r.parentNode.removeChild(r),t({width:e,height:n})}var r=document.createElement("img");r.onload=function(){n(Math.max(r.width,r.clientWidth),Math.max(r.height,r.clientHeight))},r.onerror=function(){n()};var i=r.style;i.visibility="hidden",i.position="fixed",i.bottom=i.left=0,i.width=i.height="auto",document.body.appendChild(r),r.src=e}function n(e,t,n){function r(e,n){return n=n||[],tinymce.each(e,function(e){var i={text:e.text||e.title};e.menu?i.menu=r(e.menu):(i.value=e.value,t(i)),n.push(i)}),n}return r(e,n||[])}function r(t){return function(){var n=e.settings.image_list;"string"==typeof n?tinymce.util.XHR.send({url:n,success:function(e){t(tinymce.util.JSON.parse(e))}}):"function"==typeof n?n(t):t(n)}}function i(r){function i(){var e,t,n,r;e=d.find("#width")[0],t=d.find("#height")[0],e&&t&&(n=e.value(),r=t.value(),d.find("#constrain")[0].checked()&&m&&p&&n&&r&&(m!=n?(r=Math.round(n/m*r),isNaN(r)||t.value(r)):(n=Math.round(r/p*n),isNaN(n)||e.value(n))),m=n,p=r)}function o(){function t(t){function n(){t.onload=t.onerror=null,e.selection&&(e.selection.select(t),e.nodeChanged())}t.onload=function(){y.width||y.height||!x||b.setAttribs(t,{width:t.clientWidth,height:t.clientHeight}),n()},t.onerror=n}var n,r;c(),i(),y=tinymce.extend(y,d.toJSON()),y.alt||(y.alt=""),y.title||(y.title=""),""===y.width&&(y.width=null),""===y.height&&(y.height=null),y.style||(y.style=null),y={src:y.src,alt:y.alt,title:y.title,width:y.width,height:y.height,style:y.style,caption:y.caption,"class":y["class"]},e.undoManager.transact(function(){function i(t){return e.schema.getTextBlockElements()[t.nodeName]}if(!y.src)return void(f&&(b.remove(f),e.focus(),e.nodeChanged()));if(""===y.title&&(y.title=null),f?b.setAttribs(f,y):(y.id="__mcenew",e.focus(),e.selection.setContent(b.createHTML("img",y)),f=b.get("__mcenew"),b.setAttrib(f,"id",null)),e.editorUpload.uploadImagesAuto(),y.caption===!1&&b.is(f.parentNode,"figure.image")&&(n=f.parentNode,b.insertAfter(f,n),b.remove(n)),y.caption!==!0)t(f);else if(!b.is(f.parentNode,"figure.image")){r=f,f=f.cloneNode(!0),n=b.create("figure",{"class":"image"}),n.appendChild(f),n.appendChild(b.create("figcaption",{contentEditable:!0},"Caption")),n.contentEditable=!1;var o=b.getParent(r,i);o?b.split(o,r,n):b.replace(n,r),e.selection.select(n)}})}function a(e){return e&&(e=e.replace(/px$/,"")),e}function s(n){var r,i,o,a=n.meta||{};g&&g.value(e.convertURL(this.value(),"src")),tinymce.each(a,function(e,t){d.find("#"+t).value(e)}),a.width||a.height||(r=e.convertURL(this.value(),"src"),i=e.settings.image_prepend_url,o=new RegExp("^(?:[a-z]+:)?//","i"),i&&!o.test(r)&&r.substring(0,i.length)!==i&&(r=i+r),this.value(r),t(e.documentBaseURI.toAbsolute(this.value()),function(e){e.width&&e.height&&x&&(m=e.width,p=e.height,d.find("#width").value(m),d.find("#height").value(p))}))}function l(e){if(e.margin){var t=e.margin.split(" ");switch(t.length){case 1:e["margin-top"]=e["margin-top"]||t[0],e["margin-right"]=e["margin-right"]||t[0],e["margin-bottom"]=e["margin-bottom"]||t[0],e["margin-left"]=e["margin-left"]||t[0];break;case 2:e["margin-top"]=e["margin-top"]||t[0],e["margin-right"]=e["margin-right"]||t[1],e["margin-bottom"]=e["margin-bottom"]||t[0],e["margin-left"]=e["margin-left"]||t[1];break;case 3:e["margin-top"]=e["margin-top"]||t[0],e["margin-right"]=e["margin-right"]||t[1],e["margin-bottom"]=e["margin-bottom"]||t[2],e["margin-left"]=e["margin-left"]||t[1];break;case 4:e["margin-top"]=e["margin-top"]||t[0],e["margin-right"]=e["margin-right"]||t[1],e["margin-bottom"]=e["margin-bottom"]||t[2],e["margin-left"]=e["margin-left"]||t[3]}delete e.margin}return e}function c(){function t(e){return e.length>0&&/^[0-9]+$/.test(e)&&(e+="px"),e}if(e.settings.image_advtab){var n=d.toJSON(),r=b.parseStyle(n.style);r=l(r),n.vspace&&(r["margin-top"]=r["margin-bottom"]=t(n.vspace)),n.hspace&&(r["margin-left"]=r["margin-right"]=t(n.hspace)),n.border&&(r["border-width"]=t(n.border)),d.find("#style").value(b.serializeStyle(b.parseStyle(b.serializeStyle(r))))}}function u(){if(e.settings.image_advtab){var t=d.toJSON(),n=b.parseStyle(t.style);d.find("#vspace").value(""),d.find("#hspace").value(""),n=l(n),(n["margin-top"]&&n["margin-bottom"]||n["margin-right"]&&n["margin-left"])&&(n["margin-top"]===n["margin-bottom"]?d.find("#vspace").value(a(n["margin-top"])):d.find("#vspace").value(""),n["margin-right"]===n["margin-left"]?d.find("#hspace").value(a(n["margin-right"])):d.find("#hspace").value("")),n["border-width"]&&d.find("#border").value(a(n["border-width"])),d.find("#style").value(b.serializeStyle(b.parseStyle(b.serializeStyle(n))))}}var d,f,h,m,p,g,v,y={},b=e.dom,x=e.settings.image_dimensions!==!1;f=e.selection.getNode(),h=b.getParent(f,"figure.image"),h&&(f=b.select("img",h)[0]),f&&("IMG"!=f.nodeName||f.getAttribute("data-mce-object")||f.getAttribute("data-mce-placeholder"))&&(f=null),f&&(m=b.getAttrib(f,"width"),p=b.getAttrib(f,"height"),y={src:b.getAttrib(f,"src"),alt:b.getAttrib(f,"alt"),title:b.getAttrib(f,"title"),"class":b.getAttrib(f,"class"),width:m,height:p,caption:!!h}),r&&(g={type:"listbox",label:"Image list",values:n(r,function(t){t.value=e.convertURL(t.value||t.url,"src")},[{text:"None",value:""}]),value:y.src&&e.convertURL(y.src,"src"),onselect:function(e){var t=d.find("#alt");(!t.value()||e.lastControl&&t.value()==e.lastControl.text())&&t.value(e.control.text()),d.find("#src").value(e.control.value()).fire("change")},onPostRender:function(){g=this}}),e.settings.image_class_list&&(v={name:"class",type:"listbox",label:"Class",values:n(e.settings.image_class_list,function(t){t.value&&(t.textStyle=function(){return e.formatter.getCssText({inline:"img",classes:[t.value]})})})});var C=[{name:"src",type:"filepicker",filetype:"image",label:"Source",autofocus:!0,onchange:s},g];e.settings.image_description!==!1&&C.push({name:"alt",type:"textbox",label:"Image description"}),e.settings.image_title&&C.push({name:"title",type:"textbox",label:"Image Title"}),x&&C.push({type:"container",label:"Dimensions",layout:"flex",direction:"row",align:"center",spacing:5,items:[{name:"width",type:"textbox",maxLength:5,size:3,onchange:i,ariaLabel:"Width"},{type:"label",text:"x"},{name:"height",type:"textbox",maxLength:5,size:3,onchange:i,ariaLabel:"Height"},{name:"constrain",type:"checkbox",checked:!0,text:"Constrain proportions"}]}),C.push(v),e.settings.image_caption&&tinymce.Env.ceFalse&&C.push({name:"caption",type:"checkbox",label:"Caption"}),e.settings.image_advtab?(f&&(f.style.marginLeft&&f.style.marginRight&&f.style.marginLeft===f.style.marginRight&&(y.hspace=a(f.style.marginLeft)),f.style.marginTop&&f.style.marginBottom&&f.style.marginTop===f.style.marginBottom&&(y.vspace=a(f.style.marginTop)),f.style.borderWidth&&(y.border=a(f.style.borderWidth)),y.style=e.dom.serializeStyle(e.dom.parseStyle(e.dom.getAttrib(f,"style")))),d=e.windowManager.open({title:"Insert/edit image",data:y,bodyType:"tabpanel",body:[{title:"General",type:"form",items:C},{title:"Advanced",type:"form",pack:"start",items:[{label:"Style",name:"style",type:"textbox",onchange:u},{type:"form",layout:"grid",packV:"start",columns:2,padding:0,alignH:["left","right"],defaults:{type:"textbox",maxWidth:50,onchange:c},items:[{label:"Vertical space",name:"vspace"},{label:"Horizontal space",name:"hspace"},{label:"Border",name:"border"}]}]}],onSubmit:o})):d=e.windowManager.open({title:"Insert/edit image",data:y,body:C,onSubmit:o})}e.on("preInit",function(){function t(e){var t=e.attr("class");return t&&/\bimage\b/.test(t)}function n(e){return function(n){function r(t){t.attr("contenteditable",e?"true":null)}for(var i,o=n.length;o--;)i=n[o],t(i)&&(i.attr("contenteditable",e?"false":null),tinymce.each(i.getAll("figcaption"),r))}}e.parser.addNodeFilter("figure",n(!0)),e.serializer.addNodeFilter("figure",n(!1))}),e.addButton("image",{icon:"image",tooltip:"Insert/edit image",onclick:r(i),stateSelector:"img:not([data-mce-object],[data-mce-placeholder]),figure.image"}),e.addMenuItem("image",{icon:"image",text:"Insert/edit image",onclick:r(i),context:"insert",prependToContext:!0}),e.addCommand("mceImage",r(i))}); \ No newline at end of file diff --git a/src/plugin/richText/tinymce/plugins/imagetools/plugin.min.js b/src/plugin/richText/tinymce/plugins/imagetools/plugin.min.js new file mode 100644 index 000000000..032d304e0 --- /dev/null +++ b/src/plugin/richText/tinymce/plugins/imagetools/plugin.min.js @@ -0,0 +1 @@ +!function(e,t){"use strict";function n(e,t){for(var n,r=[],o=0;oi?360+i:i,(90==i||270==i)&&t.resize(a,a.height,a.width),(90==i||180==i)&&(c=a.width),(270==i||180==i)&&(u=a.height),l.translate(c,u),l.rotate(i*Math.PI/180),l.drawImage(o,0,0),s(o),e.canvasToBlob(a,r.type)})}function i(r,i){return e.blobToImage(r).then(function(r){var o=t.create(n.getWidth(r),n.getHeight(r)),a=t.get2dContext(o);return"v"==i?(a.scale(1,-1),a.drawImage(r,0,-o.height)):(a.scale(-1,1),a.drawImage(r,-o.width,0)),s(r),e.canvasToBlob(o)})}function o(n,r,i,o,a){return e.blobToImage(n).then(function(n){var l=t.create(o,a),c=t.get2dContext(l);return c.drawImage(n,-r,-i),s(n),e.canvasToBlob(l)})}function a(n,r,i){return e.blobToImage(n).then(function(o){var a=t.create(r,i),l=t.get2dContext(a);return l.drawImage(o,0,0,r,i),s(o),e.canvasToBlob(a,n.type)})}var s=e.revokeImageUrl;return{rotate:r,flip:i,crop:o,resize:a}}),r("tinymce/imagetoolsplugin/CropRect",["tinymce/dom/DomQuery","tinymce/ui/DragHelper","tinymce/geom/Rect","tinymce/util/Tools","tinymce/util/Observable"],function(e,t,n,r,i){var o=0;return function(a,s,l,c){function u(e,t){return{x:t.x+e.x,y:t.y+e.y,w:t.w,h:t.h}}function d(e,t){return{x:t.x-e.x,y:t.y-e.y,w:t.w,h:t.h}}function f(){return d(l,a)}function h(){function i(e){var r;return new t(S,{document:c.ownerDocument,handle:S+"-"+e.name,start:function(){r=a},drag:function(t){var i,o,s,c,u;i=r.x,o=r.y,s=r.w,c=r.h,i+=t.deltaX*e.deltaX,o+=t.deltaY*e.deltaY,s+=t.deltaX*e.deltaW,c+=t.deltaY*e.deltaH,20>s&&(s=20),20>c&&(c=20),u=a=n.clamp({x:i,y:o,w:s,h:c},l,"move"==e.name),u=d(l,u),C.fire("updateRect",{rect:u}),y(u)}})}e('
').appendTo(c),r.each(E,function(t){e("#"+S,c).append(''},postRender:function(){var e=this;e._super(),e.resizeDragHelper=new t(this._id,{start:function(){e.fire("ResizeStart")},drag:function(t){"both"!=e.settings.direction&&(t.deltaX=0),e.fire("Resize",t)},stop:function(){e.fire("ResizeEnd")}})},remove:function(){return this.resizeDragHelper&&this.resizeDragHelper.destroy(),this._super()}})}),r(It,[ke],function(e){function t(e){var t="";if(e)for(var n=0;n'+e[n]+"";return t}return e.extend({Defaults:{classes:"selectbox",role:"selectbox",options:[]},init:function(e){var t=this;t._super(e),t.settings.size&&(t.size=t.settings.size),t.settings.options&&(t._options=t.settings.options)},options:function(e){return arguments.length?(this.state.set("options",e),this):this.state.get("options")},renderHtml:function(){var e=this,n,r="";return n=t(e._options),e.size&&(r=' size = "'+e.size+'"'),'"},bindStates:function(){var e=this;return e.state.on("change:options",function(n){e.getEl().innerHTML=t(n.value)}),e._super()}})}),r(Ft,[ke,ve,ce],function(e,t,n){function r(e,t,n){return t>e&&(e=t),e>n&&(e=n),e}function i(e,t){var r,i,o,a,s;"v"==e.settings.orientation?(a="top",o="height",i="h"):(a="left",o="width",i="w"),r=(e.layoutRect()[i]||100)-n.getSize(e.getEl("handle"))[o],s=r*((t-e._minValue)/(e._maxValue-e._minValue))+"px",e.getEl("handle").style[a]=s,e.getEl("handle").style.height=e.layoutRect().h+"px"}return e.extend({init:function(e){var t=this;e.previewFilter||(e.previewFilter=function(e){return Math.round(100*e)/100}),t._super(e),t.classes.add("slider"),"v"==e.orientation&&t.classes.add("vertical"),t._minValue=e.minValue||0,t._maxValue=e.maxValue||100,t._initValue=t.state.get("value")},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix;return'
'},reset:function(){this.value(this._initValue).repaint()},postRender:function(){var e=this,i,o,a=0,s,l,c,u,d,f,h,p;l=e._minValue,c=e._maxValue,s=e.value(),"v"==e.settings.orientation?(d="screenY",f="top",h="height",p="h"):(d="screenX",f="left",h="width",p="w"),e._super(),e._dragHelper=new t(e._id,{handle:e._id+"-handle",start:function(t){i=t[d],o=parseInt(e.getEl("handle").style[f],10),u=(e.layoutRect()[p]||100)-n.getSize(e.getEl("handle"))[h],e.fire("dragstart",{value:s})},drag:function(t){var n=t[d]-i,h=e.getEl("handle");a=r(o+n,0,u),h.style[f]=a+"px",s=l+a/u*(c-l),e.value(s),e.tooltip().text(""+e.settings.previewFilter(s)).show().moveRel(h,"bc tc"),e.fire("drag",{value:s})},stop:function(){e.tooltip().hide(),e.fire("dragend",{value:s})}})},repaint:function(){this._super(),i(this,this.value())},bindStates:function(){var e=this;return e.state.on("change:value",function(t){i(e,t.value)}),e._super()}})}),r(zt,[ke],function(e){return e.extend({renderHtml:function(){var e=this;return e.classes.add("spacer"),e.canFocus=!1,'
'}})}),r(Wt,[Dt,ce,g],function(e,t,n){return e.extend({Defaults:{classes:"widget btn splitbtn",role:"button"},repaint:function(){var e=this,r=e.getEl(),i=e.layoutRect(),o,a;return e._super(),o=r.firstChild,a=r.lastChild,n(o).css({width:i.w-t.getSize(a).width,height:i.h-2}),n(a).css({height:i.h-2}),e},activeMenu:function(e){var t=this;n(t.getEl().lastChild).toggleClass(t.classPrefix+"active",e)},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix,r,i=e.state.get("icon"),o=e.state.get("text"),a="";return r=e.settings.image,r?(i="none","string"!=typeof r&&(r=window.getSelection?r[0]:r[1]),r=" style=\"background-image: url('"+r+"')\""):r="",i=e.settings.icon?n+"ico "+n+"i-"+i:"",o&&(e.classes.add("btn-has-text"),a=''+e.encode(o)+""),'
'},postRender:function(){var e=this,t=e.settings.onclick;return e.on("click",function(e){var n=e.target;if(e.control==this)for(;n;){if(e.aria&&"down"!=e.aria.key||"BUTTON"==n.nodeName&&-1==n.className.indexOf("open"))return e.stopImmediatePropagation(),void(t&&t.call(this,e));n=n.parentNode}}),delete e.settings.onclick,e._super()}})}),r(Vt,[_t],function(e){return e.extend({Defaults:{containerClass:"stack-layout",controlClass:"stack-layout-item",endClass:"break"},isNative:function(){return!0}})}),r(Ut,[be,g,ce],function(e,t,n){return e.extend({Defaults:{layout:"absolute",defaults:{type:"panel"}},activateTab:function(e){var n;this.activeTabId&&(n=this.getEl(this.activeTabId),t(n).removeClass(this.classPrefix+"active"),n.setAttribute("aria-selected","false")),this.activeTabId="t"+e,n=this.getEl("t"+e),n.setAttribute("aria-selected","true"),t(n).addClass(this.classPrefix+"active"),this.items()[e].show().fire("showtab"),this.reflow(),this.items().each(function(t,n){e!=n&&t.hide()})},renderHtml:function(){var e=this,t=e._layout,n="",r=e.classPrefix;return e.preRender(),t.preRender(e),e.items().each(function(t,i){var o=e._id+"-t"+i;t.aria("role","tabpanel"),t.aria("labelledby",o),n+='"}),'
'+n+'
'+t.renderHtml(e)+"
"},postRender:function(){var e=this;e._super(),e.settings.activeTab=e.settings.activeTab||0,e.activateTab(e.settings.activeTab),this.on("click",function(t){var n=t.target.parentNode;if(t.target.parentNode.id==e._id+"-head")for(var r=n.childNodes.length;r--;)n.childNodes[r]==t.target&&e.activateTab(r)})},initLayoutRect:function(){var e=this,t,r,i;r=n.getSize(e.getEl("head")).width,r=0>r?0:r,i=0,e.items().each(function(e){r=Math.max(r,e.layoutRect().minW),i=Math.max(i,e.layoutRect().minH)}),e.items().each(function(e){e.settings.x=0,e.settings.y=0,e.settings.w=r,e.settings.h=i,e.layoutRect({x:0,y:0,w:r,h:i})});var o=n.getSize(e.getEl("head")).height;return e.settings.minWidth=r,e.settings.minHeight=i+o,t=e._super(),t.deltaH+=o,t.innerH=t.h-t.deltaH,t}})}),r($t,[ke],function(e){return e.extend({init:function(e){var t=this;t._super(e),t.classes.add("textbox"),e.multiline?t.classes.add("multiline"):(t.on("keydown",function(e){var n;13==e.keyCode&&(e.preventDefault(),t.parents().reverse().each(function(e){return e.toJSON?(n=e,!1):void 0}),t.fire("submit",{data:n.toJSON()}))}),t.on("keyup",function(e){t.state.set("value",e.target.value)}))},repaint:function(){var e=this,t,n,r,i,o=0,a;t=e.getEl().style,n=e._layoutRect,a=e._lastRepaintRect||{};var s=document;return!e.settings.multiline&&s.all&&(!s.documentMode||s.documentMode<=8)&&(t.lineHeight=n.h-o+"px"),r=e.borderBox,i=r.left+r.right+8,o=r.top+r.bottom+(e.settings.multiline?8:0),n.x!==a.x&&(t.left=n.x+"px",a.x=n.x),n.y!==a.y&&(t.top=n.y+"px",a.y=n.y),n.w!==a.w&&(t.width=n.w-i+"px",a.w=n.w),n.h!==a.h&&(t.height=n.h-o+"px",a.h=n.h),e._lastRepaintRect=a,e.fire("repaint",{},!1),e},renderHtml:function(){var e=this,t=e._id,n=e.settings,r=e.encode(e.state.get("value"),!1),i="";return"spellcheck"in n&&(i+=' spellcheck="'+n.spellcheck+'"'),n.maxLength&&(i+=' maxlength="'+n.maxLength+'"'),n.size&&(i+=' size="'+n.size+'"'),n.subtype&&(i+=' type="'+n.subtype+'"'),e.disabled()&&(i+=' disabled="disabled"'),n.multiline?'":'"},value:function(e){return arguments.length?(this.state.set("value",e),this):(this.state.get("rendered")&&this.state.set("value",this.getEl().value),this.state.get("value"))},postRender:function(){var e=this;e._super(),e.$el.on("change",function(t){e.state.set("value",t.target.value),e.fire("change",t)})},bindStates:function(){var e=this;return e.state.on("change:value",function(t){e.getEl().value!=t.value&&(e.getEl().value=t.value)}),e.state.on("change:disabled",function(t){e.getEl().disabled=t.value}),e._super()},remove:function(){this.$el.off(),this._super()}})}),r(qt,[g,he,u],function(e,t,n){return function(r,i){var o=this,a,s=t.classPrefix;o.show=function(t,l){return o.hide(),a=!0,n.setTimeout(function(){a&&(e(r).append('
'),l&&l())},t),o},o.hide=function(){var e=r.lastChild;return e&&-1!=e.className.indexOf("throbber")&&e.parentNode.removeChild(e),a=!1,o}}}),a([l,c,u,d,f,h,m,g,v,y,C,w,E,N,T,A,B,D,M,L,P,H,I,F,j,Y,G,J,ee,te,ne,re,oe,se,le,fe,he,pe,me,ge,ve,ye,be,Ce,xe,we,Ee,Ne,_e,Se,ke,Te,Re,Ae,Me,Pe,Ke,Ge,Je,Qe,et,tt,nt,rt,it,ot,at,st,lt,ct,ut,dt,ft,ht,pt,mt,gt,vt,yt,bt,Ct,xt,wt,Et,Nt,_t,St,kt,Tt,Rt,At,Bt,Dt,Mt,Lt,Pt,Ht,Ot,It,Ft,zt,Wt,Vt,Ut,$t,qt])}(this); \ No newline at end of file From 5ecfef92ff32294e11910caccbfa50138674b666 Mon Sep 17 00:00:00 2001 From: wangcongowen Date: Sun, 5 Apr 2020 19:59:58 -0400 Subject: [PATCH 06/12] Added Plugin Categories --- demo.html | 12 + pkg/Makefile | 9 +- .../categories/jquery-i18n-master/.gitignore | 2 + .../categories/jquery-i18n-master/LICENSE | 19 ++ .../categories/jquery-i18n-master/README.md | 135 +++++++++++ .../jquery-i18n-master/SpecRunner.html | 23 ++ .../categories/jquery-i18n-master/bower.json | 23 ++ .../jquery-i18n-master/examples/index.html | 81 +++++++ .../lib/jasmine-1.2.0/MIT.LICENSE | 20 ++ .../jquery-i18n-master/package.json | 17 ++ src/plugin/categories/categories.js | 209 ++++++++++++++++++ src/plugin/categories/en/annotator.js | 17 ++ 12 files changed, 564 insertions(+), 3 deletions(-) create mode 100644 pkg/plugin/categories/jquery-i18n-master/.gitignore create mode 100644 pkg/plugin/categories/jquery-i18n-master/LICENSE create mode 100644 pkg/plugin/categories/jquery-i18n-master/README.md create mode 100644 pkg/plugin/categories/jquery-i18n-master/SpecRunner.html create mode 100644 pkg/plugin/categories/jquery-i18n-master/bower.json create mode 100644 pkg/plugin/categories/jquery-i18n-master/examples/index.html create mode 100644 pkg/plugin/categories/jquery-i18n-master/lib/jasmine-1.2.0/MIT.LICENSE create mode 100644 pkg/plugin/categories/jquery-i18n-master/package.json create mode 100644 src/plugin/categories/categories.js create mode 100644 src/plugin/categories/en/annotator.js diff --git a/demo.html b/demo.html index e8bba8a38..84bf729b2 100644 --- a/demo.html +++ b/demo.html @@ -58,6 +58,12 @@ + + + + + + @@ -132,6 +138,12 @@

Header Level 3

force: location.search.indexOf('force') > -1, useHighlighter: location.search.indexOf('highlighter') > -1 }) + // Categories plugin need to be initicated before the Elasticsearch plugin + .annotator('addPlugin', 'Categories',{ + errata:'annotator-hl-errata', + destacat:'annotator-hl-destacat', + subratllat:'annotator-hl-subratllat' + }) .annotator('addPlugin', 'Elasticsearch', { online: function() { return jQuery("#status").text("Online"); diff --git a/pkg/Makefile b/pkg/Makefile index c7a80224e..bf8c54d44 100644 --- a/pkg/Makefile +++ b/pkg/Makefile @@ -37,7 +37,8 @@ PLUGINS_RESOURCES=\ plugin/annotator.touch.css PLUGINS_JAVASCRIPT=\ - plugin/richText + plugin/richText \ + plugin/categories ANNOTATOR_FULL=\ $(ANNOTATOR) \ @@ -81,8 +82,10 @@ plugins-resources: @cp ../src/$(PLUGINS_RESOURCES) ../css/`echo $(PLUGINS_RESOURCES) | sed 's:.*/::'` plugins_javascript: - @mkdir -p $(PLUGINS_JAVASCRIPT) - @cp -r ../src/$(PLUGINS_JAVASCRIPT) plugin + @for f in $(PLUGINS_JAVASCRIPT); do \ + mkdir -p $$f; \ + cp -r ../src/$$f plugin; \ + done annotator-full: annotator-full.min.js diff --git a/pkg/plugin/categories/jquery-i18n-master/.gitignore b/pkg/plugin/categories/jquery-i18n-master/.gitignore new file mode 100644 index 000000000..a56a7ef43 --- /dev/null +++ b/pkg/plugin/categories/jquery-i18n-master/.gitignore @@ -0,0 +1,2 @@ +node_modules + diff --git a/pkg/plugin/categories/jquery-i18n-master/LICENSE b/pkg/plugin/categories/jquery-i18n-master/LICENSE new file mode 100644 index 000000000..978ee2ae8 --- /dev/null +++ b/pkg/plugin/categories/jquery-i18n-master/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Dave Perrett, http://recursive-design.com/ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/pkg/plugin/categories/jquery-i18n-master/README.md b/pkg/plugin/categories/jquery-i18n-master/README.md new file mode 100644 index 000000000..9ac4977ba --- /dev/null +++ b/pkg/plugin/categories/jquery-i18n-master/README.md @@ -0,0 +1,135 @@ + +About +----- + +_jQuery-i18n_ is a jQuery plugin for doing client-side translations in javascript. It is based heavily on [javascript i18n that almost doesn't suck](http://markos.gaivo.net/blog/?p=100) by Marko Samastur, and is licensed under the [MIT license](http://www.opensource.org/licenses/mit-license.php). + +Installation +------------ + +You'll need to download the [jQuery library](http://docs.jquery.com/Downloading_jQuery#Current_Release), and include it before _jquery.i18n.js_ in your HTML source. See the _examples_ folder for examples. + +This library is also available as a [bower](http://bower.io/) component under the name *jquery-i18n*. + +Usage +----- + +Before you can do any translation you have to initialise the plugin with a 'dictionary' (basically a property list mapping keys to their translations). + +```javascript +var my_dictionary = { + 'some text': 'a translation', + 'some more text': 'another translation' +} +$.i18n.load(my_dictionary); +``` + +Once you've initialised it with a dictionary, you can translate strings using the $.i18n._() function, for example: + +```javascript +$('div#example').text($.i18n._('some text')); +``` + +or using $('selector')._t() function + +```javascript +$('div#example')._t('some text'); +``` + +Wildcards +--------- + +It's straightforward to pass dynamic data into your translations. First, add _%s_ in the translation for each variable you want to swap in : + +```javascript +var my_dictionary = { + "wildcard example" : "We have been passed two values : %s and %s." +} +$.i18n.load(my_dictionary); +``` + +Next, pass values in sequence after the dictionary key when you perform the translation : + +```javascript +$('div#example').text($.i18n._('wildcard example', 100, 200)); +``` + +or + +```javascript +$('div#example')._t('wildcard example', 100, 200); +``` + +This will output _We have been passed two values : 100 and 200._ + +Because some languages will need to order arguments differently to english, you can also specify the order in which the variables appear : + +```javascript +var my_dictionary = { + "wildcard example" : "We have been passed two values : %2$s and %1$s." +} +$.i18n.load(my_dictionary); + +$('div#example').text($.i18n._('wildcard example', 100, 200)); +``` + +This will output: _We have been passed two values: 200 and 100._ + +If you need to explicitly output the string _%s_ in your translation, use _%%s_ : + +```javascript +var my_dictionary = { + "wildcard example" : "I have %s literal %%s character." +} +$.i18n.load(my_dictionary); + +$('div#example').text($.i18n._('wildcard example', 1)); +``` + +This will output: _I have 1 literal %%s character._ + +Building From Scratch +--------------------- + +Use `npm install` to install the dependencies, and `grunt` to run the build. + + +Change history +----------- + +* **Version 1.1.1 (2014-01-05)** : Use html() instead of text() when rendering translations. +* **Version 1.1.0 (2013-12-31)** : Use grunt, update printf implementation, `setDictionary` is now `load` (thanks to [ktmud](https://github.com/ktmud)). +* **Version 1.0.1 (2013-10-11)** : Add bower support. +* **Version 1.0.0 (2012-10-14)** : 1.0 release - addition of a test suite (huge thanks to [alexaitken](https://github.com/alexaitken)), plus a major cleanup. + +Bug Reports +----------- + +If you come across any problems, please [create a ticket](https://github.com/recurser/jquery-i18n/issues) and we'll try to get it fixed as soon as possible. + + +Contributing +------------ + +Once you've made your commits: + +1. [Fork](http://help.github.com/fork-a-repo/) jquery-i18n +2. Create a topic branch - `git checkout -b my_branch` +3. Push to your branch - `git push origin my_branch` +4. Create a [Pull Request](http://help.github.com/pull-requests/) from your branch +5. That's it! + + +Author +------ + +Dave Perrett :: hello@daveperrett.com :: [@daveperrett](http://twitter.com/daveperrett) + + +Copyright +--------- + +Copyright (c) 2010 Dave Perrett. See [License](https://github.com/recurser/jquery-i18n/blob/master/LICENSE) for details. + + + diff --git a/pkg/plugin/categories/jquery-i18n-master/SpecRunner.html b/pkg/plugin/categories/jquery-i18n-master/SpecRunner.html new file mode 100644 index 000000000..550d81a4f --- /dev/null +++ b/pkg/plugin/categories/jquery-i18n-master/SpecRunner.html @@ -0,0 +1,23 @@ + + + + jasmine-sinon specs + + + + + + + + + + + + + + + + diff --git a/pkg/plugin/categories/jquery-i18n-master/bower.json b/pkg/plugin/categories/jquery-i18n-master/bower.json new file mode 100644 index 000000000..e7af1cdb9 --- /dev/null +++ b/pkg/plugin/categories/jquery-i18n-master/bower.json @@ -0,0 +1,23 @@ +{ + "name": "jquery-i18n", + "version": "1.1.0", + "homepage": "https://github.com/recurser/jquery-i18n", + "authors": [ + "Dave Perrett " + ], + "description": "A jQuery plugin for doing client-side translations in javascript.", + "main": "jquery.i18n.js", + "keywords": [ + "jquery", + "i18n", + "translation" + ], + "license": "MIT", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ] +} \ No newline at end of file diff --git a/pkg/plugin/categories/jquery-i18n-master/examples/index.html b/pkg/plugin/categories/jquery-i18n-master/examples/index.html new file mode 100644 index 000000000..c50711ef9 --- /dev/null +++ b/pkg/plugin/categories/jquery-i18n-master/examples/index.html @@ -0,0 +1,81 @@ + + + + +jQuery i18n Plugin + + + + + + + +

+ Click the button to translate the following text into some random Finnish from the + Wikipedia Finnish Phonology Article +

+ +
Example 1
+
Example 2
+
Example 3
+
Example 4
+
Example 5
+
Example 6
+
Example 7
+
Example 8
+
Example 9
+
Example 10
+
Dynamic Content
+
Ordered Dynamic Content
+
HTML Content
+ + + + diff --git a/pkg/plugin/categories/jquery-i18n-master/lib/jasmine-1.2.0/MIT.LICENSE b/pkg/plugin/categories/jquery-i18n-master/lib/jasmine-1.2.0/MIT.LICENSE new file mode 100644 index 000000000..7c435baae --- /dev/null +++ b/pkg/plugin/categories/jquery-i18n-master/lib/jasmine-1.2.0/MIT.LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2008-2011 Pivotal Labs + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/pkg/plugin/categories/jquery-i18n-master/package.json b/pkg/plugin/categories/jquery-i18n-master/package.json new file mode 100644 index 000000000..5f1c7cc92 --- /dev/null +++ b/pkg/plugin/categories/jquery-i18n-master/package.json @@ -0,0 +1,17 @@ +{ + "name": "jquery-i18n", + "description": "A jQuery plugin for doing client-side translations in javascript.", + "repository": "git@github.com:recurser/jquery-i18n.git", + "version": "1.1.1", + "main": "Gruntfile.js", + "dependencies": { + }, + "devDependencies": { + "grunt-contrib-uglify": "~0.2.0", + "grunt": "~0.4.0" + }, + "peerDependencies": { + "grunt": "~0.4.0" + } +} + diff --git a/src/plugin/categories/categories.js b/src/plugin/categories/categories.js new file mode 100644 index 000000000..ee770aa1d --- /dev/null +++ b/src/plugin/categories/categories.js @@ -0,0 +1,209 @@ +/* +Annotator view panel Plugin v1.0 (https://https://github.com/albertjuhe/annotator_view/) +Copyright (C) 2014 Albert Juhé Brugué +License: https://github.com/albertjuhe/annotator_view/License.rst +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +(function() { + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + Annotator.Plugin.Categories = (function(_super) { + __extends(Categories, _super); + + + Categories.prototype.events = { + 'annotationsLoaded': 'onAnnotationsLoaded' + }; + + Categories.prototype.field = null; + + Categories.prototype.input = null; + + Categories.prototype.options = { + categories: {} + }; + + function Categories(element, categories) { + this.setAnnotationCat = __bind(this.setAnnotationCat, this); + this.updateField = __bind(this.updateField, this); + this.onAnnotationUpdated = __bind(this.onAnnotationUpdated, this); + this.annotationCreated = __bind(this.annotationCreated, this); + this.AnnotationSection = __bind(this.AnnotationSection, this); + this.AnnotationCategory = __bind(this.AnnotationCategory, this); + this.updateAnnotation = __bind(this.updateAnnotation, this); + + this.options.categories = categories; + Categories.__super__.constructor.apply(this, arguments); + } + + + Categories.prototype.pluginInit = function() { + if (!Annotator.supported()) { + return; + } + + //Call editor after submit. + this.annotator.subscribe("annotationEditorSubmit",this.AnnotationSection); + + //Call editor before show and write color checker + this.annotator.subscribe("annotationEditorShown",this.AnnotationCategory); + + //Annotation creation + this.annotator.subscribe("annotationCreated",this.annotationCreated); + + //Showing annotations + this.annotator.subscribe("annotationViewerShown",this.AnnotationViewer); + + this.annotator.subscribe("annotationUpdated ",this.updateAnnotation); + + }; + + //After loading annotations we want to change the annotation color and add the annotation id + Categories.prototype.onAnnotationsLoaded = function(annotations) { + var annotation; + var _categories = this.options.categories; //Categories plug-in + + $('#count-anotations').text( annotations.length ); + if (annotations.length > 0) { + for(i=0, len = annotations.length; i < len; i++) { + annotation = annotations[i]; + var category = "annotator-hl-" + annotation.category; + if (annotation.category in _categories) { + category = _categories[annotation.category]; + } + $(annotation.highlights).addClass(category); + $(annotation.highlights).attr('id', annotation.id ); + } + + } + + }; + + //After loading annotations we want to change the annotation color and add the annotation id + Categories.prototype.updateAnnotation = function(annotation) { + + var category = this.options.categories[annotation.category]; + + $(annotation.highlights).attr("class","annotator-hl " + category); + + }; + + //After loading annotations we want to change the annotation color and add the annotation id + Categories.prototype.AnnotationViewer = function(viewer, annotations) { + var annotation; + var isShared = ""; + var class_label="label"; + + if (annotations.length > 0) { + for(i=0, len = annotations.length; i < len; i++) { + annotation = annotations[i]; + + if (annotation.estat==1 || annotation.permissions.read.length===0 ) { + isShared = "" + } + if (annotation.propietary==0) { + class_label = "label-compartit"; + } + //$('ul.annotator-widget > li.annotator-item').prepend('
'); + $( "div.annotator-user" ).html( ""+annotation.user+""+isShared); + + } + } + } + + + //Section order and section title + Categories.prototype.AnnotationSection = function(editor,annotation) { + //Assign a categoy to the annotation + + //Put the annotation section an annotation title + var ref = $('.annotator-hl-temporary').closest('div[data-section]'); + if (ref) { + annotation.section = ref.data('section'); + annotation.section_title = ref.data('title'); + } else { + console.log("Section not detected!!!") + } + annotation.order = $('.annotator-hl-temporary').closest('div[id]').attr('id'); + annotation.category = $('input:radio[name=categories-annotation]:checked').val(); + + } + + //Create the categories section inside the editor + Categories.prototype.AnnotationCategory = function(editor,annotation) { + var _categories = this.options.categories; //Categories plug-in + var editor = $('form.annotator-widget > ul.annotator-listing'); //Place to add categories. + if ($('li.annotator-radio').length == 0) { //If the category section not exists + editor.append("
  • "); + var _radioGroup = $('li.annotator-radio'); //Place to add radiobuttons + var checked = "checked = 'checked'"; + i=1; + for (cat in _categories) { + if (i>1) checked=""; + var radio =""; + radio = radio + '
    '; + i = i + 1; + _radioGroup.append(radio); + } + + } + if (annotation.category) { + $('#' + annotation.category).prop('checked',true); + } + } + + //When an annotation is changed we have to change the attributes + Categories.prototype.onAnnotationUpdated = function(annotation) { + $( "span[id="+annotation.id+"]" ).attr('class','annotator-hl-'+annotation.category); + }; + + + Categories.prototype.annotationCreated = function(annotation) { + var cat, h, highlights, _i, _len, _results; + + $( "span[id="+annotation.id+"]" ).attr('id',annotation.id); + cat = annotation.category; + highlights = annotation.highlights; + if (cat) { //If have a category + _results = []; + for (_i = 0, _len = highlights.length; _i < _len; _i++) { + h = highlights[_i]; + _results.push(h.className = h.className + ' ' + this.options.categories[cat]); + } + return _results; + } + }; + + Categories.prototype.updateField = function(field, annotation) { + var category; + category = ''; + if (field.checked = 'checked') { + category = annotation.category; + } + console.log('updateField'); + return this.input.val(category); + }; + + Categories.prototype.updateViewer = function(field, annotation) { + field = $(field); + field.html('' +$.i18n._(annotation.category).toUpperCase() + '').addClass('annotator-hl-'+ annotation.category ); + + }; + + return Categories; + + })(Annotator.Plugin); + +}).call(this); diff --git a/src/plugin/categories/en/annotator.js b/src/plugin/categories/en/annotator.js new file mode 100644 index 000000000..7b216067c --- /dev/null +++ b/src/plugin/categories/en/annotator.js @@ -0,0 +1,17 @@ +var i18n_dict = { + "Comments" : "Comments", + "requires_jQuery" :"Annotator requires jQuery: have you included lib/vendor/jquery.js?", + "requires_JSON" : "Annotator requires a JSON implementation: have you included lib/vendor/json2.js?", + "Cancel" : "Cancel", + "Save" : "Save", + "view_annotation" : "Allow anyone to view this annotation", + "edit_annotation" : "Allow anyone to edit this annotation", + "No Comment" : "No Comment", + "Summary" : "Summary", + "view_annotations" : "View annotations", + "doesnot_suport" : "Sorry your current browser does not support the Annotator", + "Edit" : "Edit", + "Delete" : "Delete", + "share" : "Shared", + "confirm_delete" : "Do you want to delete this annotation?" + }; \ No newline at end of file From cd80d21707d37a32ce256855402d5ff758ab3c72 Mon Sep 17 00:00:00 2001 From: wangcongowen Date: Sun, 5 Apr 2020 21:20:40 -0400 Subject: [PATCH 07/12] Added text color picker to Tinymce --- demo.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/demo.html b/demo.html index 84bf729b2..89618f2d3 100644 --- a/demo.html +++ b/demo.html @@ -157,11 +157,12 @@

    Header Level 3

    .annotator('addPlugin','RichText',{ tinymce:{ selector: "li.annotator-item textarea", - plugins: "media image insertdatetime link code", + plugins: "insertdatetime link code textcolor colorpicker autosave", + autosave_ask_before_unload: false, menubar: false, toolbar_items_size: 'small', extended_valid_elements : "iframe[src|frameborder|style|scrolling|class|width|height|name|align|id]", - toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image media rubric | code ", + toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | code | forecolor backcolor", } }); From e1e9d91c29ef48b0c5138e88ee8f12e04bc4f133 Mon Sep 17 00:00:00 2001 From: wangcongowen Date: Sun, 5 Apr 2020 21:33:30 -0400 Subject: [PATCH 08/12] Added resource files for Categories plugin --- src/plugin/categories/categories.css | 17 + .../categories/jquery-i18n-master/.gitignore | 2 + .../jquery-i18n-master/Gruntfile.js | 35 + .../categories/jquery-i18n-master/LICENSE | 19 + .../categories/jquery-i18n-master/README.md | 135 + .../jquery-i18n-master/SpecRunner.html | 23 + .../categories/jquery-i18n-master/bower.json | 23 + .../jquery-i18n-master/examples/index.html | 81 + .../examples/jquery-1.4.2.js | 6852 +++++++++++++++++ .../jquery-i18n-master/jquery.i18n.js | 103 + .../jquery-i18n-master/jquery.i18n.min.js | 1 + .../lib/jasmine-1.2.0/MIT.LICENSE | 20 + .../lib/jasmine-1.2.0/jasmine-html.js | 617 ++ .../lib/jasmine-1.2.0/jasmine.css | 81 + .../lib/jasmine-1.2.0/jasmine.js | 2529 ++++++ .../jquery-i18n-master/package.json | 17 + .../specs/jquery.i18n.spec.js | 69 + .../jquery-i18n-master/src/jquery.i18n.js | 103 + src/plugin/categories/locale/en/annotator.js | 17 + 19 files changed, 10744 insertions(+) create mode 100644 src/plugin/categories/categories.css create mode 100644 src/plugin/categories/jquery-i18n-master/.gitignore create mode 100644 src/plugin/categories/jquery-i18n-master/Gruntfile.js create mode 100644 src/plugin/categories/jquery-i18n-master/LICENSE create mode 100644 src/plugin/categories/jquery-i18n-master/README.md create mode 100644 src/plugin/categories/jquery-i18n-master/SpecRunner.html create mode 100644 src/plugin/categories/jquery-i18n-master/bower.json create mode 100644 src/plugin/categories/jquery-i18n-master/examples/index.html create mode 100644 src/plugin/categories/jquery-i18n-master/examples/jquery-1.4.2.js create mode 100644 src/plugin/categories/jquery-i18n-master/jquery.i18n.js create mode 100644 src/plugin/categories/jquery-i18n-master/jquery.i18n.min.js create mode 100644 src/plugin/categories/jquery-i18n-master/lib/jasmine-1.2.0/MIT.LICENSE create mode 100644 src/plugin/categories/jquery-i18n-master/lib/jasmine-1.2.0/jasmine-html.js create mode 100644 src/plugin/categories/jquery-i18n-master/lib/jasmine-1.2.0/jasmine.css create mode 100644 src/plugin/categories/jquery-i18n-master/lib/jasmine-1.2.0/jasmine.js create mode 100644 src/plugin/categories/jquery-i18n-master/package.json create mode 100644 src/plugin/categories/jquery-i18n-master/specs/jquery.i18n.spec.js create mode 100644 src/plugin/categories/jquery-i18n-master/src/jquery.i18n.js create mode 100644 src/plugin/categories/locale/en/annotator.js diff --git a/src/plugin/categories/categories.css b/src/plugin/categories/categories.css new file mode 100644 index 000000000..f56bb4e8f --- /dev/null +++ b/src/plugin/categories/categories.css @@ -0,0 +1,17 @@ +.annotator-hl-errata { + background: #ffcfbf; + cursor:pointer; +} + +.annotator-hl-destacat { + background: #dfffbf; + cursor:pointer; +} + +.annotator-hl-subratllat { + background: rgba(255, 255, 10, 0.3); + text-decoration:underline; + text-decoration-color: red; + text-decoration-style: wavy; + cursor:pointer; +} \ No newline at end of file diff --git a/src/plugin/categories/jquery-i18n-master/.gitignore b/src/plugin/categories/jquery-i18n-master/.gitignore new file mode 100644 index 000000000..a56a7ef43 --- /dev/null +++ b/src/plugin/categories/jquery-i18n-master/.gitignore @@ -0,0 +1,2 @@ +node_modules + diff --git a/src/plugin/categories/jquery-i18n-master/Gruntfile.js b/src/plugin/categories/jquery-i18n-master/Gruntfile.js new file mode 100644 index 000000000..48af1c718 --- /dev/null +++ b/src/plugin/categories/jquery-i18n-master/Gruntfile.js @@ -0,0 +1,35 @@ + +module.exports = function(grunt) { + + grunt.initConfig({ + meta: { + date: (new Date()).toUTCString() + }, + pkg: grunt.file.readJSON('package.json'), + uglify: { + dist: { + src: 'jquery.i18n.js', + dest: 'jquery.i18n.min.js' + } + } + }); + + grunt.registerTask('build', function() { + var content = grunt.file.read('src/jquery.i18n.js', 'utf-8'); + var output = grunt.template.process(content); + grunt.file.write('jquery.i18n.js', output); + grunt.log.ok('File jquery.i18n.js created.'); + }); + + // update bower version + grunt.registerTask('bower', function() { + var pkg = grunt.file.readJSON('package.json'); + var bower = grunt.file.readJSON('bower.json'); + bower.version = pkg.version; + grunt.file.write('bower.json', JSON.stringify(bower, null, 2)); + }); + + grunt.registerTask('default', ['build', 'uglify']); + + grunt.loadNpmTasks('grunt-contrib-uglify'); +}; diff --git a/src/plugin/categories/jquery-i18n-master/LICENSE b/src/plugin/categories/jquery-i18n-master/LICENSE new file mode 100644 index 000000000..978ee2ae8 --- /dev/null +++ b/src/plugin/categories/jquery-i18n-master/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Dave Perrett, http://recursive-design.com/ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/src/plugin/categories/jquery-i18n-master/README.md b/src/plugin/categories/jquery-i18n-master/README.md new file mode 100644 index 000000000..9ac4977ba --- /dev/null +++ b/src/plugin/categories/jquery-i18n-master/README.md @@ -0,0 +1,135 @@ + +About +----- + +_jQuery-i18n_ is a jQuery plugin for doing client-side translations in javascript. It is based heavily on [javascript i18n that almost doesn't suck](http://markos.gaivo.net/blog/?p=100) by Marko Samastur, and is licensed under the [MIT license](http://www.opensource.org/licenses/mit-license.php). + +Installation +------------ + +You'll need to download the [jQuery library](http://docs.jquery.com/Downloading_jQuery#Current_Release), and include it before _jquery.i18n.js_ in your HTML source. See the _examples_ folder for examples. + +This library is also available as a [bower](http://bower.io/) component under the name *jquery-i18n*. + +Usage +----- + +Before you can do any translation you have to initialise the plugin with a 'dictionary' (basically a property list mapping keys to their translations). + +```javascript +var my_dictionary = { + 'some text': 'a translation', + 'some more text': 'another translation' +} +$.i18n.load(my_dictionary); +``` + +Once you've initialised it with a dictionary, you can translate strings using the $.i18n._() function, for example: + +```javascript +$('div#example').text($.i18n._('some text')); +``` + +or using $('selector')._t() function + +```javascript +$('div#example')._t('some text'); +``` + +Wildcards +--------- + +It's straightforward to pass dynamic data into your translations. First, add _%s_ in the translation for each variable you want to swap in : + +```javascript +var my_dictionary = { + "wildcard example" : "We have been passed two values : %s and %s." +} +$.i18n.load(my_dictionary); +``` + +Next, pass values in sequence after the dictionary key when you perform the translation : + +```javascript +$('div#example').text($.i18n._('wildcard example', 100, 200)); +``` + +or + +```javascript +$('div#example')._t('wildcard example', 100, 200); +``` + +This will output _We have been passed two values : 100 and 200._ + +Because some languages will need to order arguments differently to english, you can also specify the order in which the variables appear : + +```javascript +var my_dictionary = { + "wildcard example" : "We have been passed two values : %2$s and %1$s." +} +$.i18n.load(my_dictionary); + +$('div#example').text($.i18n._('wildcard example', 100, 200)); +``` + +This will output: _We have been passed two values: 200 and 100._ + +If you need to explicitly output the string _%s_ in your translation, use _%%s_ : + +```javascript +var my_dictionary = { + "wildcard example" : "I have %s literal %%s character." +} +$.i18n.load(my_dictionary); + +$('div#example').text($.i18n._('wildcard example', 1)); +``` + +This will output: _I have 1 literal %%s character._ + +Building From Scratch +--------------------- + +Use `npm install` to install the dependencies, and `grunt` to run the build. + + +Change history +----------- + +* **Version 1.1.1 (2014-01-05)** : Use html() instead of text() when rendering translations. +* **Version 1.1.0 (2013-12-31)** : Use grunt, update printf implementation, `setDictionary` is now `load` (thanks to [ktmud](https://github.com/ktmud)). +* **Version 1.0.1 (2013-10-11)** : Add bower support. +* **Version 1.0.0 (2012-10-14)** : 1.0 release - addition of a test suite (huge thanks to [alexaitken](https://github.com/alexaitken)), plus a major cleanup. + +Bug Reports +----------- + +If you come across any problems, please [create a ticket](https://github.com/recurser/jquery-i18n/issues) and we'll try to get it fixed as soon as possible. + + +Contributing +------------ + +Once you've made your commits: + +1. [Fork](http://help.github.com/fork-a-repo/) jquery-i18n +2. Create a topic branch - `git checkout -b my_branch` +3. Push to your branch - `git push origin my_branch` +4. Create a [Pull Request](http://help.github.com/pull-requests/) from your branch +5. That's it! + + +Author +------ + +Dave Perrett :: hello@daveperrett.com :: [@daveperrett](http://twitter.com/daveperrett) + + +Copyright +--------- + +Copyright (c) 2010 Dave Perrett. See [License](https://github.com/recurser/jquery-i18n/blob/master/LICENSE) for details. + + + diff --git a/src/plugin/categories/jquery-i18n-master/SpecRunner.html b/src/plugin/categories/jquery-i18n-master/SpecRunner.html new file mode 100644 index 000000000..550d81a4f --- /dev/null +++ b/src/plugin/categories/jquery-i18n-master/SpecRunner.html @@ -0,0 +1,23 @@ + + + + jasmine-sinon specs + + + + + + + + + + + + + + + + diff --git a/src/plugin/categories/jquery-i18n-master/bower.json b/src/plugin/categories/jquery-i18n-master/bower.json new file mode 100644 index 000000000..e7af1cdb9 --- /dev/null +++ b/src/plugin/categories/jquery-i18n-master/bower.json @@ -0,0 +1,23 @@ +{ + "name": "jquery-i18n", + "version": "1.1.0", + "homepage": "https://github.com/recurser/jquery-i18n", + "authors": [ + "Dave Perrett " + ], + "description": "A jQuery plugin for doing client-side translations in javascript.", + "main": "jquery.i18n.js", + "keywords": [ + "jquery", + "i18n", + "translation" + ], + "license": "MIT", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ] +} \ No newline at end of file diff --git a/src/plugin/categories/jquery-i18n-master/examples/index.html b/src/plugin/categories/jquery-i18n-master/examples/index.html new file mode 100644 index 000000000..c50711ef9 --- /dev/null +++ b/src/plugin/categories/jquery-i18n-master/examples/index.html @@ -0,0 +1,81 @@ + + + + +jQuery i18n Plugin + + + + + + + +

    + Click the button to translate the following text into some random Finnish from the + Wikipedia Finnish Phonology Article +

    + +
    Example 1
    +
    Example 2
    +
    Example 3
    +
    Example 4
    +
    Example 5
    +
    Example 6
    +
    Example 7
    +
    Example 8
    +
    Example 9
    +
    Example 10
    +
    Dynamic Content
    +
    Ordered Dynamic Content
    +
    HTML Content
    + + + + diff --git a/src/plugin/categories/jquery-i18n-master/examples/jquery-1.4.2.js b/src/plugin/categories/jquery-i18n-master/examples/jquery-1.4.2.js new file mode 100644 index 000000000..fc56f3b95 --- /dev/null +++ b/src/plugin/categories/jquery-i18n-master/examples/jquery-1.4.2.js @@ -0,0 +1,6852 @@ +/*! + * jQuery JavaScript Library v1.4.2 + * http://jquery.com/ + * + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Sat Feb 13 22:33:48 2010 -0500 + */ +(function( window, undefined ) { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // Use the correct document accordingly with window argument (sandbox) + document = window.document, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/, + + // Is it a simple selector + isSimple = /^.[^:#\[\.,]*$/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + rtrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // Has the ready events already been bound? + readyBound = false, + + // The functions to execute on DOM ready + readyList = [], + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwnProperty = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + indexOf = Array.prototype.indexOf; + +jQuery.fn = jQuery.prototype = { + init: function( selector, context ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context ) { + this.context = document; + this[0] = document.body; + this.selector = "body"; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + match = quickExpr.exec( selector ); + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + if ( elem ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $("TAG") + } else if ( !context && /^\w+$/.test( selector ) ) { + this.selector = selector; + this.context = document; + selector = document.getElementsByTagName( selector ); + return jQuery.merge( this, selector ); + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return jQuery( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.4.2", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = jQuery(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // If the DOM is already ready + if ( jQuery.isReady ) { + // Execute the function immediately + fn.call( document, jQuery ); + + // Otherwise, remember the function for later + } else if ( readyList ) { + // Add the function to the wait list + readyList.push( fn ); + } + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || jQuery(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + // copy reference to target object + var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging object literal values or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) { + var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src + : jQuery.isArray(copy) ? [] : {}; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + window.$ = _$; + + if ( deep ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // Handle when the DOM is ready + ready: function() { + // Make sure that the DOM is not already loaded + if ( !jQuery.isReady ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 13 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If there are functions bound, to execute + if ( readyList ) { + // Execute all of them + var fn, i = 0; + while ( (fn = readyList[ i++ ]) ) { + fn.call( document, jQuery ); + } + + // Reset the list of functions + readyList = null; + } + + // Trigger any bound ready events + if ( jQuery.fn.triggerHandler ) { + jQuery( document ).triggerHandler( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyBound ) { + return; + } + + readyBound = true; + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + return jQuery.ready(); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent("onreadystatechange", DOMContentLoaded); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return toString.call(obj) === "[object Function]"; + }, + + isArray: function( obj ) { + return toString.call(obj) === "[object Array]"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) { + return false; + } + + // Not own constructor property must be Object + if ( obj.constructor + && !hasOwnProperty.call(obj, "constructor") + && !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwnProperty.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( /^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@") + .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]") + .replace(/(?:^|:|,)(?:\s*\[)+/g, "")) ) { + + // Try to use the native JSON parser first + return window.JSON && window.JSON.parse ? + window.JSON.parse( data ) : + (new Function("return " + data))(); + + } else { + jQuery.error( "Invalid JSON: " + data ); + } + }, + + noop: function() {}, + + // Evalulates a script in a global context + globalEval: function( data ) { + if ( data && rnotwhite.test(data) ) { + // Inspired by code by Andrea Giammarchi + // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html + var head = document.getElementsByTagName("head")[0] || document.documentElement, + script = document.createElement("script"); + + script.type = "text/javascript"; + + if ( jQuery.support.scriptEval ) { + script.appendChild( document.createTextNode( data ) ); + } else { + script.text = data; + } + + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709). + head.insertBefore( script, head.firstChild ); + head.removeChild( script ); + } + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction(object); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( var value = object[0]; + i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} + } + } + + return object; + }, + + trim: function( text ) { + return (text || "").replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + if ( array.length == null || typeof array === "string" || jQuery.isFunction(array) || (typeof array !== "function" && array.setInterval) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + if ( array.indexOf ) { + return array.indexOf( elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = []; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + if ( !inv !== !callback( elems[ i ], i ) ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var ret = [], value; + + // Go through the array, translating each of the items to their + // new value (or values). + for ( var i = 0, length = elems.length; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + proxy: function( fn, proxy, thisObject ) { + if ( arguments.length === 2 ) { + if ( typeof proxy === "string" ) { + thisObject = fn; + fn = thisObject[ proxy ]; + proxy = undefined; + + } else if ( proxy && !jQuery.isFunction( proxy ) ) { + thisObject = proxy; + proxy = undefined; + } + } + + if ( !proxy && fn ) { + proxy = function() { + return fn.apply( thisObject || this, arguments ); + }; + } + + // Set the guid of unique handler to the same of original handler, so it can be removed + if ( fn ) { + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + } + + // So proxy can be declared as an argument + return proxy; + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = /(webkit)[ \/]([\w.]+)/.exec( ua ) || + /(opera)(?:.*version)?[ \/]([\w.]+)/.exec( ua ) || + /(msie) ([\w.]+)/.exec( ua ) || + !/compatible/.test( ua ) && /(mozilla)(?:.*? rv:([\w.]+))?/.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + browser: {} +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +if ( indexOf ) { + jQuery.inArray = function( elem, array ) { + return indexOf.call( array, elem ); + }; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch( error ) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +function evalScript( i, elem ) { + if ( elem.src ) { + jQuery.ajax({ + url: elem.src, + async: false, + dataType: "script" + }); + } else { + jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); + } + + if ( elem.parentNode ) { + elem.parentNode.removeChild( elem ); + } +} + +// Mutifunctional method to get and set values to a collection +// The value/s can be optionally by executed if its a function +function access( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; +} + +function now() { + return (new Date).getTime(); +} +(function() { + + jQuery.support = {}; + + var root = document.documentElement, + script = document.createElement("script"), + div = document.createElement("div"), + id = "script" + now(); + + div.style.display = "none"; + div.innerHTML = "
    a"; + + var all = div.getElementsByTagName("*"), + a = div.getElementsByTagName("a")[0]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return; + } + + jQuery.support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: div.firstChild.nodeType === 3, + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText insted) + style: /red/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: a.getAttribute("href") === "/a", + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55$/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: div.getElementsByTagName("input")[0].value === "on", + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: document.createElement("select").appendChild( document.createElement("option") ).selected, + + parentNode: div.removeChild( div.appendChild( document.createElement("div") ) ).parentNode === null, + + // Will be defined later + deleteExpando: true, + checkClone: false, + scriptEval: false, + noCloneEvent: true, + boxModel: null + }; + + script.type = "text/javascript"; + try { + script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); + } catch(e) {} + + root.insertBefore( script, root.firstChild ); + + // Make sure that the execution of code works by injecting a script + // tag with appendChild/createTextNode + // (IE doesn't support this, fails, and uses .text instead) + if ( window[ id ] ) { + jQuery.support.scriptEval = true; + delete window[ id ]; + } + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete script.test; + + } catch(e) { + jQuery.support.deleteExpando = false; + } + + root.removeChild( script ); + + if ( div.attachEvent && div.fireEvent ) { + div.attachEvent("onclick", function click() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + jQuery.support.noCloneEvent = false; + div.detachEvent("onclick", click); + }); + div.cloneNode(true).fireEvent("onclick"); + } + + div = document.createElement("div"); + div.innerHTML = ""; + + var fragment = document.createDocumentFragment(); + fragment.appendChild( div.firstChild ); + + // WebKit doesn't clone checked state correctly in fragments + jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked; + + // Figure out if the W3C box model works as expected + // document.body must exist before we can do this + jQuery(function() { + var div = document.createElement("div"); + div.style.width = div.style.paddingLeft = "1px"; + + document.body.appendChild( div ); + jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; + document.body.removeChild( div ).style.display = 'none'; + + div = null; + }); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + var eventSupported = function( eventName ) { + var el = document.createElement("div"); + eventName = "on" + eventName; + + var isSupported = (eventName in el); + if ( !isSupported ) { + el.setAttribute(eventName, "return;"); + isSupported = typeof el[eventName] === "function"; + } + el = null; + + return isSupported; + }; + + jQuery.support.submitBubbles = eventSupported("submit"); + jQuery.support.changeBubbles = eventSupported("change"); + + // release memory in IE + root = script = div = all = a = null; +})(); + +jQuery.props = { + "for": "htmlFor", + "class": "className", + readonly: "readOnly", + maxlength: "maxLength", + cellspacing: "cellSpacing", + rowspan: "rowSpan", + colspan: "colSpan", + tabindex: "tabIndex", + usemap: "useMap", + frameborder: "frameBorder" +}; +var expando = "jQuery" + now(), uuid = 0, windowData = {}; + +jQuery.extend({ + cache: {}, + + expando:expando, + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + "object": true, + "applet": true + }, + + data: function( elem, name, data ) { + if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { + return; + } + + elem = elem == window ? + windowData : + elem; + + var id = elem[ expando ], cache = jQuery.cache, thisCache; + + if ( !id && typeof name === "string" && data === undefined ) { + return null; + } + + // Compute a unique ID for the element + if ( !id ) { + id = ++uuid; + } + + // Avoid generating a new cache unless none exists and we + // want to manipulate it. + if ( typeof name === "object" ) { + elem[ expando ] = id; + thisCache = cache[ id ] = jQuery.extend(true, {}, name); + + } else if ( !cache[ id ] ) { + elem[ expando ] = id; + cache[ id ] = {}; + } + + thisCache = cache[ id ]; + + // Prevent overriding the named cache with undefined values + if ( data !== undefined ) { + thisCache[ name ] = data; + } + + return typeof name === "string" ? thisCache[ name ] : thisCache; + }, + + removeData: function( elem, name ) { + if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { + return; + } + + elem = elem == window ? + windowData : + elem; + + var id = elem[ expando ], cache = jQuery.cache, thisCache = cache[ id ]; + + // If we want to remove a specific section of the element's data + if ( name ) { + if ( thisCache ) { + // Remove the section of cache data + delete thisCache[ name ]; + + // If we've removed all the data, remove the element's cache + if ( jQuery.isEmptyObject(thisCache) ) { + jQuery.removeData( elem ); + } + } + + // Otherwise, we want to remove all of the element's data + } else { + if ( jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } + + // Completely remove the data cache + delete cache[ id ]; + } + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + if ( typeof key === "undefined" && this.length ) { + return jQuery.data( this[0] ); + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + } + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + } else { + return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function() { + jQuery.data( this, key, value ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); +jQuery.extend({ + queue: function( elem, type, data ) { + if ( !elem ) { + return; + } + + type = (type || "fx") + "queue"; + var q = jQuery.data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( !data ) { + return q || []; + } + + if ( !q || jQuery.isArray(data) ) { + q = jQuery.data( elem, type, jQuery.makeArray(data) ); + + } else { + q.push( data ); + } + + return q; + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), fn = queue.shift(); + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function( i, elem ) { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + } +}); +var rclass = /[\n\t]/g, + rspace = /\s+/, + rreturn = /\r/g, + rspecialurl = /href|src|style/, + rtype = /(button|input)/i, + rfocusable = /(button|input|object|select|textarea)/i, + rclickable = /^(a|area)$/i, + rradiocheck = /radio|checkbox/; + +jQuery.fn.extend({ + attr: function( name, value ) { + return access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name, fn ) { + return this.each(function(){ + jQuery.attr( this, name, "" ); + if ( this.nodeType === 1 ) { + this.removeAttribute( name ); + } + }); + }, + + addClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.addClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( value && typeof value === "string" ) { + var classNames = (value || "").split( rspace ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className ) { + elem.className = value; + + } else { + var className = " " + elem.className + " ", setClass = elem.className; + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { + setClass += " " + classNames[c]; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.removeClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + var classNames = (value || "").split(rspace); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + var className = (" " + elem.className + " ").replace(rclass, " "); + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[c] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function(i) { + var self = jQuery(this); + self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, i = 0, self = jQuery(this), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery.data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + if ( value === undefined ) { + var elem = this[0]; + + if ( elem ) { + if ( jQuery.nodeName( elem, "option" ) ) { + return (elem.attributes.value || {}).specified ? elem.value : elem.text; + } + + // We need to handle select boxes special + if ( jQuery.nodeName( elem, "select" ) ) { + var index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + if ( option.selected ) { + // Get the specifc value for the option + value = jQuery(option).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + } + + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) { + return elem.getAttribute("value") === null ? "on" : elem.value; + } + + + // Everything else, we just grab the value + return (elem.value || "").replace(rreturn, ""); + + } + + return undefined; + } + + var isFunction = jQuery.isFunction(value); + + return this.each(function(i) { + var self = jQuery(this), val = value; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call(this, i, self.val()); + } + + // Typecast each time if the value is a Function and the appended + // value is therefore different each time. + if ( typeof val === "number" ) { + val += ""; + } + + if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) { + this.checked = jQuery.inArray( self.val(), val ) >= 0; + + } else if ( jQuery.nodeName( this, "select" ) ) { + var values = jQuery.makeArray(val); + + jQuery( "option", this ).each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + this.selectedIndex = -1; + } + + } else { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attr: function( elem, name, value, pass ) { + // don't set attributes on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery(elem)[name](value); + } + + var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ), + // Whether we are setting (or getting) + set = value !== undefined; + + // Try to normalize/fix the name + name = notxml && jQuery.props[ name ] || name; + + // Only do all the following if this is a node (faster for style) + if ( elem.nodeType === 1 ) { + // These attributes require special treatment + var special = rspecialurl.test( name ); + + // Safari mis-reports the default selected property of an option + // Accessing the parent's selectedIndex property fixes it + if ( name === "selected" && !jQuery.support.optSelected ) { + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + + // If applicable, access the attribute via the DOM 0 way + if ( name in elem && notxml && !special ) { + if ( set ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } + + elem[ name ] = value; + } + + // browsers index elements by id/name on forms, give priority to attributes. + if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) { + return elem.getAttributeNode( name ).nodeValue; + } + + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + if ( name === "tabIndex" ) { + var attributeNode = elem.getAttributeNode( "tabIndex" ); + + return attributeNode && attributeNode.specified ? + attributeNode.value : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + + return elem[ name ]; + } + + if ( !jQuery.support.style && notxml && name === "style" ) { + if ( set ) { + elem.style.cssText = "" + value; + } + + return elem.style.cssText; + } + + if ( set ) { + // convert the value to a string (all browsers do this but IE) see #1070 + elem.setAttribute( name, "" + value ); + } + + var attr = !jQuery.support.hrefNormalized && notxml && special ? + // Some attributes require a special call on IE + elem.getAttribute( name, 2 ) : + elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return attr === null ? undefined : attr; + } + + // elem is actually elem.style ... set the style + // Using attr for specific style information is now deprecated. Use style instead. + return jQuery.style( elem, name, value ); + } +}); +var rnamespaces = /\.(.*)$/, + fcleanup = function( nm ) { + return nm.replace(/[^\w\s\.\|`]/g, function( ch ) { + return "\\" + ch; + }); + }; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // For whatever reason, IE has trouble passing the window object + // around, causing it to be cloned in the process + if ( elem.setInterval && ( elem !== window && !elem.frameElement ) ) { + elem = window; + } + + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure + var elemData = jQuery.data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + var events = elemData.events = elemData.events || {}, + eventHandle = elemData.handle, eventHandle; + + if ( !eventHandle ) { + elemData.handle = eventHandle = function() { + // Handle the second event of a trigger and when + // an event is called after a page has unloaded + return typeof jQuery !== "undefined" && !jQuery.event.triggered ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split(" "); + + var type, i = 0, namespaces; + + while ( (type = types[ i++ ]) ) { + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; + + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handleObj.namespace = ""; + } + + handleObj.type = type; + handleObj.guid = handler.guid; + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = jQuery.event.special[ type ] || {}; + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = []; + + // Check for a special event handler + // Only use addEventListener/attachEvent if the special + // events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add the function to the element's handler list + handlers.push( handleObj ); + + // Keep track of which events have been used, for global triggering + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, pos ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + var ret, type, fn, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + elemData = jQuery.data( elem ), + events = elemData && elemData.events; + + if ( !elemData || !events ) { + return; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)") + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( var j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } + } + + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( var j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); + } + + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + + if ( pos != null ) { + break; + } + } + } + + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + removeEvent( elem, type, elemData.handle ); + } + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem ); + } + } + }, + + // bubbling is internal + trigger: function( event, data, elem /*, bubbling */ ) { + // Event object or event type + var type = event.type || event, + bubbling = arguments[3]; + + if ( !bubbling ) { + event = typeof event === "object" ? + // jQuery.Event object + event[expando] ? event : + // Object literal + jQuery.extend( jQuery.Event(type), event ) : + // Just the event type (string) + jQuery.Event(type); + + if ( type.indexOf("!") >= 0 ) { + event.type = type = type.slice(0, -1); + event.exclusive = true; + } + + // Handle a global trigger + if ( !elem ) { + // Don't bubble custom events when global (to avoid too much overhead) + event.stopPropagation(); + + // Only trigger if we've ever bound an event for it + if ( jQuery.event.global[ type ] ) { + jQuery.each( jQuery.cache, function() { + if ( this.events && this.events[type] ) { + jQuery.event.trigger( event, data, this.handle.elem ); + } + }); + } + } + + // Handle triggering a single element + + // don't do events on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { + return undefined; + } + + // Clean up in case it is reused + event.result = undefined; + event.target = elem; + + // Clone the incoming data, if any + data = jQuery.makeArray( data ); + data.unshift( event ); + } + + event.currentTarget = elem; + + // Trigger the event, it is assumed that "handle" is a function + var handle = jQuery.data( elem, "handle" ); + if ( handle ) { + handle.apply( elem, data ); + } + + var parent = elem.parentNode || elem.ownerDocument; + + // Trigger an inline bound script + try { + if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) { + if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) { + event.result = false; + } + } + + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (e) {} + + if ( !event.isPropagationStopped() && parent ) { + jQuery.event.trigger( event, data, parent, true ); + + } else if ( !event.isDefaultPrevented() ) { + var target = event.target, old, + isClick = jQuery.nodeName(target, "a") && type === "click", + special = jQuery.event.special[ type ] || {}; + + if ( (!special._default || special._default.call( elem, event ) === false) && + !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) { + + try { + if ( target[ type ] ) { + // Make sure that we don't accidentally re-trigger the onFOO events + old = target[ "on" + type ]; + + if ( old ) { + target[ "on" + type ] = null; + } + + jQuery.event.triggered = true; + target[ type ](); + } + + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (e) {} + + if ( old ) { + target[ "on" + type ] = old; + } + + jQuery.event.triggered = false; + } + } + }, + + handle: function( event ) { + var all, handlers, namespaces, namespace, events; + + event = arguments[0] = jQuery.event.fix( event || window.event ); + event.currentTarget = this; + + // Namespaced event handlers + all = event.type.indexOf(".") < 0 && !event.exclusive; + + if ( !all ) { + namespaces = event.type.split("."); + event.type = namespaces.shift(); + namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + var events = jQuery.data(this, "events"), handlers = events[ event.type ]; + + if ( events && handlers ) { + // Clone the handlers to prevent manipulation + handlers = handlers.slice(0); + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + + // Filter the functions by class + if ( all || namespace.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, arguments ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + } + + return event.result; + }, + + props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), + + fix: function( event ) { + if ( event[ expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var doc = document.documentElement, body = document.body; + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) { + event.which = event.charCode || event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( handleObj ) { + jQuery.event.add( this, handleObj.origType, jQuery.extend({}, handleObj, {handler: liveHandler}) ); + }, + + remove: function( handleObj ) { + var remove = true, + type = handleObj.origType.replace(rnamespaces, ""); + + jQuery.each( jQuery.data(this, "events").live || [], function() { + if ( type === this.origType.replace(rnamespaces, "") ) { + remove = false; + return false; + } + }); + + if ( remove ) { + jQuery.event.remove( this, handleObj.origType, liveHandler ); + } + } + + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( this.setInterval ) { + this.onbeforeunload = eventHandle; + } + + return false; + }, + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + } +}; + +var removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + elem.removeEventListener( type, handle, false ); + } : + function( elem, type, handle ) { + elem.detachEvent( "on" + type, handle ); + }; + +jQuery.Event = function( src ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + // Event type + } else { + this.type = src; + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = now(); + + // Mark it as fixed + this[ expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + } + // otherwise set the returnValue property of the original event to false (IE) + e.returnValue = false; + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + // Check if mouse(over|out) are still within the same parent element + var parent = event.relatedTarget; + + // Firefox sometimes assigns relatedTarget a XUL element + // which we cannot access the parentNode property of + try { + // Traverse up the tree + while ( parent && parent !== this ) { + parent = parent.parentNode; + } + + if ( parent !== this ) { + // set the correct event type + event.type = event.data; + + // handle event if we actually just moused on to a non sub-element + jQuery.event.handle.apply( this, arguments ); + } + + // assuming we've left the element since we most likely mousedover a xul element + } catch(e) { } +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( this.nodeName.toLowerCase() !== "form" ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + var elem = e.target, type = elem.type; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + return trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit", function( e ) { + var elem = e.target, type = elem.type; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + return trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + + var formElems = /textarea|input|select/i, + + changeFilters, + + getVal = function( elem ) { + var type = elem.type, val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( elem.nodeName.toLowerCase() === "select" ) { + val = elem.selectedIndex; + } + + return val; + }, + + testChange = function testChange( e ) { + var elem = e.target, data, val; + + if ( !formElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery.data( elem, "_change_data" ); + val = getVal(elem); + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery.data( elem, "_change_data", val ); + } + + if ( data === undefined || val === data ) { + return; + } + + if ( data != null || val ) { + e.type = "change"; + return jQuery.event.trigger( e, arguments[1], elem ); + } + }; + + jQuery.event.special.change = { + filters: { + focusout: testChange, + + click: function( e ) { + var elem = e.target, type = elem.type; + + if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) { + return testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = elem.type; + + if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + return testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information/focus[in] is not needed anymore + beforeactivate: function( e ) { + var elem = e.target; + jQuery.data( elem, "_change_data", getVal(elem) ); + } + }, + + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } + + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); + } + + return formElems.test( this.nodeName ); + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); + + return formElems.test( this.nodeName ); + } + }; + + changeFilters = jQuery.event.special.change.filters; +} + +function trigger( type, elem, args ) { + args[0].type = type; + return jQuery.event.handle.apply( elem, args ); +} + +// Create "bubbling" focus and blur events +if ( document.addEventListener ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + jQuery.event.special[ fix ] = { + setup: function() { + this.addEventListener( orig, handler, true ); + }, + teardown: function() { + this.removeEventListener( orig, handler, true ); + } + }; + + function handler( e ) { + e = jQuery.event.fix( e ); + e.type = fix; + return jQuery.event.handle.call( this, e ); + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( jQuery.isFunction( data ) ) { + fn = data; + data = undefined; + } + + var handler = name === "one" ? jQuery.proxy( fn, function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }) : fn; + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + var event = jQuery.Event( type ); + event.preventDefault(); + event.stopPropagation(); + jQuery.event.trigger( event, data, this[0] ); + return event.result; + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, i = 1; + + // link all the functions, so any of them can unbind this click handler + while ( i < args.length ) { + jQuery.proxy( fn, args[ i++ ] ); + } + + return this.click( jQuery.proxy( fn, function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + })); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + +jQuery.each(["live", "die"], function( i, name ) { + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( jQuery.isFunction( data ) ) { + fn = data; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( type === "focus" || type === "blur" ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + context.each(function(){ + jQuery.event.add( this, liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + }); + + } else { + // unbind live handler + context.unbind( liveConvert( type, selector ), fn ); + } + } + + return this; + } +}); + +function liveHandler( event ) { + var stop, elems = [], selectors = [], args = arguments, + related, match, handleObj, elem, j, i, l, data, + events = jQuery.data( this, "events" ); + + // Make sure we avoid non-left-click bubbling in Firefox (#3861) + if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) { + return; + } + + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); + + } else { + live.splice( j--, 1 ); + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( match[i].selector === handleObj.selector ) { + elem = match[i].elem; + related = null; + + // Those two events require additional checking + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, handleObj: handleObj }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + event.currentTarget = match.elem; + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + if ( match.handleObj.origHandler.apply( match.elem, args ) === false ) { + stop = false; + break; + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return "live." + (type && type !== "*" ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&"); +} + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( fn ) { + return fn ? this.bind( name, fn ) : this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + +// Prevent memory leaks in IE +// Window isn't included so as not to unbind existing unload events +// More info: +// - http://isaacschlueter.com/2006/10/msie-memory-leaks/ +if ( window.attachEvent && !window.addEventListener ) { + window.attachEvent("onunload", function() { + for ( var id in jQuery.cache ) { + if ( jQuery.cache[ id ].handle ) { + // Try/Catch is to handle iframes being unloaded, see #4280 + try { + jQuery.event.remove( jQuery.cache[ id ].handle.elem ); + } catch(e) {} + } + } + }); +} +/*! + * Sizzle CSS Selector Engine - v1.0 + * Copyright 2009, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function(){ + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function(selector, context, results, seed) { + results = results || []; + var origContext = context = context || document; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var parts = [], m, set, checkSet, extra, prune = true, contextXML = isXML(context), + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + var ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; + } + + if ( context ) { + var ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray(set); + } else { + prune = false; + } + + while ( parts.length ) { + var cur = parts.pop(), pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + } else if ( context && context.nodeType === 1 ) { + for ( var i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + } else { + for ( var i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function(results){ + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort(sortOrder); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[i-1] ) { + results.splice(i--, 1); + } + } + } + } + + return results; +}; + +Sizzle.matches = function(expr, set){ + return Sizzle(expr, null, null, set); +}; + +Sizzle.find = function(expr, context, isXML){ + var set, match; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var type = Expr.order[i], match; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice(1,1); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace(/\\/g, ""); + set = Expr.find[ type ]( match, context, isXML ); + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = context.getElementsByTagName("*"); + } + + return {set: set, expr: expr}; +}; + +Sizzle.filter = function(expr, set, inplace, not){ + var old = expr, result = [], curLoop = set, match, anyFound, + isXMLFilter = set && set[0] && isXML(set[0]); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var filter = Expr.filter[ type ], found, item, left = match[1]; + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + } else { + curLoop[i] = false; + } + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + match: { + ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + leftMatch: {}, + attrMap: { + "class": "className", + "for": "htmlFor" + }, + attrHandle: { + href: function(elem){ + return elem.getAttribute("href"); + } + }, + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !/\W/.test(part), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + ">": function(checkSet, part){ + var isPartStr = typeof part === "string"; + + if ( isPartStr && !/\W/.test(part) ) { + part = part.toLowerCase(); + + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + } else { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + "": function(checkSet, part, isXML){ + var doneName = done++, checkFn = dirCheck; + + if ( typeof part === "string" && !/\W/.test(part) ) { + var nodeCheck = part = part.toLowerCase(); + checkFn = dirNodeCheck; + } + + checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); + }, + "~": function(checkSet, part, isXML){ + var doneName = done++, checkFn = dirCheck; + + if ( typeof part === "string" && !/\W/.test(part) ) { + var nodeCheck = part = part.toLowerCase(); + checkFn = dirNodeCheck; + } + + checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); + } + }, + find: { + ID: function(match, context, isXML){ + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + return m ? [m] : []; + } + }, + NAME: function(match, context){ + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], results = context.getElementsByName(match[1]); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + TAG: function(match, context){ + return context.getElementsByTagName(match[1]); + } + }, + preFilter: { + CLASS: function(match, curLoop, inplace, result, not, isXML){ + match = " " + match[1].replace(/\\/g, "") + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + ID: function(match){ + return match[1].replace(/\\/g, ""); + }, + TAG: function(match, curLoop){ + return match[1].toLowerCase(); + }, + CHILD: function(match){ + if ( match[1] === "nth" ) { + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + ATTR: function(match, curLoop, inplace, result, not, isXML){ + var name = match[1].replace(/\\/g, ""); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + PSEUDO: function(match, curLoop, inplace, result, not){ + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + if ( !inplace ) { + result.push.apply( result, ret ); + } + return false; + } + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + POS: function(match){ + match.unshift( true ); + return match; + } + }, + filters: { + enabled: function(elem){ + return elem.disabled === false && elem.type !== "hidden"; + }, + disabled: function(elem){ + return elem.disabled === true; + }, + checked: function(elem){ + return elem.checked === true; + }, + selected: function(elem){ + // Accessing this property makes selected-by-default + // options in Safari work properly + elem.parentNode.selectedIndex; + return elem.selected === true; + }, + parent: function(elem){ + return !!elem.firstChild; + }, + empty: function(elem){ + return !elem.firstChild; + }, + has: function(elem, i, match){ + return !!Sizzle( match[3], elem ).length; + }, + header: function(elem){ + return /h\d/i.test( elem.nodeName ); + }, + text: function(elem){ + return "text" === elem.type; + }, + radio: function(elem){ + return "radio" === elem.type; + }, + checkbox: function(elem){ + return "checkbox" === elem.type; + }, + file: function(elem){ + return "file" === elem.type; + }, + password: function(elem){ + return "password" === elem.type; + }, + submit: function(elem){ + return "submit" === elem.type; + }, + image: function(elem){ + return "image" === elem.type; + }, + reset: function(elem){ + return "reset" === elem.type; + }, + button: function(elem){ + return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; + }, + input: function(elem){ + return /input|select|textarea|button/i.test(elem.nodeName); + } + }, + setFilters: { + first: function(elem, i){ + return i === 0; + }, + last: function(elem, i, match, array){ + return i === array.length - 1; + }, + even: function(elem, i){ + return i % 2 === 0; + }, + odd: function(elem, i){ + return i % 2 === 1; + }, + lt: function(elem, i, match){ + return i < match[3] - 0; + }, + gt: function(elem, i, match){ + return i > match[3] - 0; + }, + nth: function(elem, i, match){ + return match[3] - 0 === i; + }, + eq: function(elem, i, match){ + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function(elem, match, i, array){ + var name = match[1], filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; + } else if ( name === "not" ) { + var not = match[3]; + + for ( var i = 0, l = not.length; i < l; i++ ) { + if ( not[i] === elem ) { + return false; + } + } + + return true; + } else { + Sizzle.error( "Syntax error, unrecognized expression: " + name ); + } + }, + CHILD: function(elem, match){ + var type = match[1], node = elem; + switch (type) { + case 'only': + case 'first': + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + if ( type === "first" ) { + return true; + } + node = elem; + case 'last': + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + return true; + case 'nth': + var first = match[2], last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + if ( first === 0 ) { + return diff === 0; + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + ID: function(elem, match){ + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + TAG: function(elem, match){ + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + CLASS: function(elem, match){ + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + ATTR: function(elem, match){ + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + POS: function(elem, match, i, array){ + var name = match[2], filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, function(all, num){ + return "\\" + (num - 0 + 1); + })); +} + +var makeArray = function(array, results) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch(e){ + makeArray = function(array, results) { + var ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + } else { + if ( typeof array.length === "number" ) { + for ( var i = 0, l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + } else { + for ( var i = 0; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.compareDocumentPosition ? -1 : 1; + } + + var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} else if ( "sourceIndex" in document.documentElement ) { + sortOrder = function( a, b ) { + if ( !a.sourceIndex || !b.sourceIndex ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.sourceIndex ? -1 : 1; + } + + var ret = a.sourceIndex - b.sourceIndex; + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} else if ( document.createRange ) { + sortOrder = function( a, b ) { + if ( !a.ownerDocument || !b.ownerDocument ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.ownerDocument ? -1 : 1; + } + + var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); + aRange.setStart(a, 0); + aRange.setEnd(a, 0); + bRange.setStart(b, 0); + bRange.setEnd(b, 0); + var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange); + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +function getText( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += getText( elem.childNodes ); + } + } + + return ret; +} + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date).getTime(); + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + var root = document.documentElement; + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function(match, context, isXML){ + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; + } + }; + + Expr.filter.ID = function(elem, match){ + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + root = form = null; // release memory in IE +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function(match, context){ + var results = context.getElementsByTagName(match[1]); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + Expr.attrHandle.href = function(elem){ + return elem.getAttribute("href", 2); + }; + } + + div = null; // release memory in IE +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, div = document.createElement("div"); + div.innerHTML = "

    "; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function(query, context, extra, seed){ + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && context.nodeType === 9 && !isXML(context) ) { + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(e){} + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + div = null; // release memory in IE + })(); +} + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
    "; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function(match, context, isXML) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + div = null; // release memory in IE +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + elem = elem[dir]; + var match = false; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + elem = elem[dir]; + var match = false; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +var contains = document.compareDocumentPosition ? function(a, b){ + return !!(a.compareDocumentPosition(b) & 16); +} : function(a, b){ + return a !== b && (a.contains ? a.contains(b) : true); +}; + +var isXML = function(elem){ + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function(selector, context){ + var tmpSet = [], later = "", match, + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = getText; +jQuery.isXMLDoc = isXML; +jQuery.contains = contains; + +return; + +window.Sizzle = Sizzle; + +})(); +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + slice = Array.prototype.slice; + +// Implement the identical functionality for filter and not +var winnow = function( elements, qualifier, keep ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +}; + +jQuery.fn.extend({ + find: function( selector ) { + var ret = this.pushStack( "", "find", selector ), length = 0; + + for ( var i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( var n = length; n < ret.length; n++ ) { + for ( var r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && jQuery.filter( selector, this ).length > 0; + }, + + closest: function( selectors, context ) { + if ( jQuery.isArray( selectors ) ) { + var ret = [], cur = this[0], match, matches = {}, selector; + + if ( cur && selectors.length ) { + for ( var i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[selector] ) { + matches[selector] = jQuery.expr.match.POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[selector]; + + if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) { + ret.push({ selector: selector, elem: cur }); + delete matches[selector]; + } + } + cur = cur.parentNode; + } + } + + return ret; + } + + var pos = jQuery.expr.match.POS.test( selectors ) ? + jQuery( selectors, context || this.context ) : null; + + return this.map(function( i, cur ) { + while ( cur && cur.ownerDocument && cur !== context ) { + if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selectors) ) { + return cur; + } + cur = cur.parentNode; + } + return null; + }); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + if ( !elem || typeof elem === "string" ) { + return jQuery.inArray( this[0], + // If it receives a string, the selector is used + // If it receives nothing, the siblings are used + elem ? jQuery( elem ) : this.parent().children() ); + } + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context || this.context ) : + jQuery.makeArray( selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, slice.call(arguments).join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], cur = elem[dir]; + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /(<([\w:]+)[^>]*?)\/>/g, + rselfClosing = /^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i, + rtagName = /<([\w:]+)/, + rtbody = /"; + }, + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
    ", "
    " ], + thead: [ 1, "", "
    " ], + tr: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + col: [ 2, "", "
    " ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and - + diff --git a/pkg/Makefile b/pkg/Makefile index bf8c54d44..276a9c947 100644 --- a/pkg/Makefile +++ b/pkg/Makefile @@ -13,6 +13,7 @@ ANNOTATOR=\ widget.coffee \ editor.coffee \ viewer.coffee \ + dictionary.coffee \ notification.coffee PLUGINS=\ diff --git a/src/annotator.coffee b/src/annotator.coffee index a354ecc2d..c9ee3d113 100644 --- a/src/annotator.coffee +++ b/src/annotator.coffee @@ -12,11 +12,14 @@ class Annotator extends Delegator events: ".annotator-adder button click": "onAdderClick" ".annotator-adder button mousedown": "onAdderMousedown" + ".annotator-dict button click": "onDictClick" + ".annotator-dict button mousedown": "onDictMousedown" ".annotator-hl mouseover": "onHighlightMouseover" ".annotator-hl mouseout": "startViewerHideTimer" html: - adder: '
    ' + adder: '
    ' + dict: '
    ' wrapper: '
    ' options: # Configuration options @@ -28,6 +31,8 @@ class Annotator extends Delegator viewer: null + dictionary: null + selectedRanges: null mouseIsDown: false @@ -66,11 +71,12 @@ class Annotator extends Delegator # Return early if the annotator is not supported. return this unless Annotator.supported() this._setupDocumentEvents() unless @options.readOnly - this._setupWrapper()._setupViewer()._setupEditor() + this._setupWrapper()._setupViewer()._setupEditor()._setupDictionary() this._setupDynamicStyle() # Create adder this.adder = $(this.html.adder).appendTo(@wrapper).hide() + this.dict = $(this.html.dict).appendTo(@wrapper).hide() Annotator._instances.push(this) @@ -135,6 +141,21 @@ class Annotator extends Delegator @editor.element.appendTo(@wrapper) this + # Creates an instance of the Annotator.Dictionary and assigns it to @dictionary. + # Appends this to the @wrapper and sets up event listeners. + # + # Returns itself for chaining. + _setupDictionary: -> + @dictionary = new Annotator.Dictionary() + @dictionary.hide() + .on('hide', this.onDictionaryHide) + .addField({ + parameter: 'test123' + }) + + @dictionary.element.appendTo(@wrapper) + this + # Sets up the selection event listeners to watch mouse actions on the document. # # Returns itself for chaining. @@ -154,7 +175,7 @@ class Annotator extends Delegator if (!style.length) style = $('').appendTo(document.head) - sel = '*' + (":not(.annotator-#{x})" for x in ['adder', 'outer', 'notice', 'filter']).join('') + sel = '*' + (":not(.annotator-#{x})" for x in ['adder','dict', 'outer', 'notice', 'filter']).join('') # use the maximum z-index in the page max = Util.maxZIndex($(document.body).find(sel)) @@ -165,7 +186,7 @@ class Annotator extends Delegator max = Math.max(max, 1000) style.text [ - ".annotator-adder, .annotator-outer, .annotator-notice {" + ".annotator-adder, .annotator-dict, .annotator-outer, .annotator-notice {" " z-index: #{max + 20};" "}" ".annotator-filter {" @@ -190,6 +211,7 @@ class Annotator extends Delegator $('#annotator-dynamic-style').remove() @adder.remove() + @dict.remove() @viewer.destroy() @editor.destroy() @@ -323,6 +345,32 @@ class Annotator extends Delegator annotation + setupSelected: (annotation) -> + root = @wrapper[0] + annotation.ranges or= @selectedRanges + + normedRanges = [] + for r in annotation.ranges + try + normedRanges.push(Range.sniff(r).normalize(root)) + catch e + if e instanceof Range.RangeError + this.publish('rangeNormalizeFail', [annotation, r, e]) + else + # Oh Javascript, why you so crap? This will lose the traceback. + throw e + + annotation.quote = [] + annotation.ranges = [] + + for normed in normedRanges + annotation.quote.push $.trim(normed.text()) + annotation.ranges.push normed.serialize(@wrapper[0], '.annotator-hl') + + # Join all the quotes into one string. + annotation.quote = annotation.quote.join(' / ') + annotation + # Public: Publishes the 'beforeAnnotationUpdated' and 'annotationUpdated' # events. Listeners wishing to modify an updated annotation should subscribe # to 'beforeAnnotationUpdated' while listeners storing annotations should @@ -553,6 +601,15 @@ class Annotator extends Delegator this.startViewerHideTimer() @mouseIsDown = true + showDictionary: (annotation, location) => + @dictionary.element.css(location) + @dictionary.load(annotation) + this + + onDictionaryHide: => + this.publish('annotationDictionaryHidden', [@dictionary]) + @ignoreMouseup = false + # Annotator#element callback. Checks to see if a selection has been made # on mouseup and if so displays the Annotator#adder. If @ignoreMouseup is # set will do nothing. Also resets the @mouseIsDown property. @@ -579,8 +636,12 @@ class Annotator extends Delegator @adder .css(Util.mousePosition(event, @wrapper[0])) .show() + @dict + .css(Util.mousePosition(event, @wrapper[0])) + .show() else @adder.hide() + @dict.hide() # Public: Determines if the provided element is part of the annotator plugin. # Useful for ignoring mouse actions on the annotator elements. @@ -652,6 +713,7 @@ class Annotator extends Delegator # Hide the adder position = @adder.position() + @dict.hide() @adder.hide() # Show a temporary highlight so the user can see what they selected @@ -684,6 +746,22 @@ class Annotator extends Delegator # Display the editor. this.showEditor(annotation, position) + onDictMousedown: (event) => + event?.preventDefault() + @ignoreMouseup = true + + onDictClick: (event) => + event?.preventDefault() + + # Hide the adder + position = @dict.position() + @dict.hide() + @adder.hide() + + annotation = this.setupSelected(this.createAnnotation()) + + this.showDictionary(annotation, position) + # Annotator#viewer callback function. Displays the Annotator#editor in the # positions of the Annotator#viewer and loads the passed annotation for # editing. diff --git a/src/plugin/richText/richText-annotator.js b/src/plugin/richText/richText-annotator.js index db0756932..ece761973 100644 --- a/src/plugin/richText/richText-annotator.js +++ b/src/plugin/richText/richText-annotator.js @@ -35,7 +35,8 @@ Annotator.Plugin.RichText = (function(_super) { menubar: false, toolbar_items_size: 'small', extended_valid_elements : "iframe[src|frameborder|style|scrolling|class|width|height|name|align|id]", - toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image media rubric | code ", + toolbar: "insertfile undo redo | styleselect | fontsizeselect | italic bold | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image media rubric | code ", + fontsize_formats: "8pt 10pt" } }; From aefd1aa5a832d93b9d98bad865d1eb64590fee45 Mon Sep 17 00:00:00 2001 From: wangcongowen Date: Fri, 14 Jan 2022 21:21:11 -0500 Subject: [PATCH 12/12] updated demo html --- demo2.html | 128 ++++++++++++++ demo3.html | 94 +++++++++++ src/dictionary.coffee | 376 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 598 insertions(+) create mode 100644 demo2.html create mode 100644 demo3.html create mode 100644 src/dictionary.coffee diff --git a/demo2.html b/demo2.html new file mode 100644 index 000000000..6c8f631bf --- /dev/null +++ b/demo2.html @@ -0,0 +1,128 @@ + + + + + Annotator demo + + + + +
    +

    Annotator demonstration

    +
    + +
    +

    + He was an old man who fished alone in a skiff in the Gulf Stream and he + had gone eighty-four days now without taking a fish. In the first forty + days a boy had been with him. But after forty days without a fish the + boy's parents had told him that the old man was now definitely and + finally salao, which is the worst form of unlucky, and the boy + had gone at their orders in another boat which caught three good fish + the first week. It made the boy sad to see the old man come in each day + with his skiff empty and he always went down to help him carry either + the coiled lines or the gaff and harpoon and the sail that was furled + around the mast. The sail was patched with flour sacks and, furled, it + looked like the flag of permanent defeat. +

    +

    + The old man was thin and gaunt with deep wrinkles in the back of his + neck. The brown blotches of the benevolent skin cancer the sun brings + from its reflection on the tropic sea were on his cheeks. The blotches + ran well down the sides of his face and his hands had the deep-creased + scars from handling heavy fish on the cords. But none of these scars + were fresh. They were as old as erosions in a fishless desert. +

    +

    + Everything about him was old except his eyes and they were the same + color as the sea and were cheerful and undefeated. +

    +

    + "Santiago," the boy said to him as they climbed the bank from + where the skiff was hauled up. "I could go with you again. We've + made some money." +

    +

    The old man had taught the boy to fish and the boy loved him.

    +

    + "No," the old man said. "You're with a lucky boat. Stay + with them." +

    +

    + "But remember how you went eighty-seven days without fish and then + we caught big ones every day for three weeks." +

    +

    + "I remember," the old man said. "I know you did not leave + me because you doubted." +

    +

    + "It was papa made me leave. I am a boy and I must obey him." +

    +

    + "I know," the old man said. "It is quite normal." +

    +

    "He hasn't much faith."

    +

    + "No," the old man said. "But we have. Haven't we?" +

    +

    + "Yes," the boy said. "Can I offer you a beer on the + Terrace and then we'll take the stuff home." +

    +

    + "Why not?" the old man said. "Between fishermen." +

    +

    + They sat on the Terrace and many of the fishermen made fun of the old + man and he was not angry. Others, of the older fishermen, looked at him + and were sad. But they did not show it and they spoke politely about the + current and the depths they had drifted their lines at and the steady + good weather and of what they had seen. The successful fishermen of that + day were already in and had butchered their marlin out and carried them + laid full length across two planks, with two men staggering at the end + of each plank, to the fish house where they waited for the ice truck to + carry them to the market in Havana. Those who had caught sharks had + taken them to the shark factory on the other side of the cove where they + were hoisted on a block and tackle, their livers removed, their fins cut + off and their hides skinned out and their flesh cut into strips for + salting. +

    +

    + When the wind was in the east a smell came across the harbour from the + shark factory; but today there was only the faint edge of the odour + because the wind had backed into the north and then dropped off and it + was pleasant and sunny on the Terrace. +

    +
    + + + + + + diff --git a/demo3.html b/demo3.html new file mode 100644 index 000000000..3471ba78e --- /dev/null +++ b/demo3.html @@ -0,0 +1,94 @@ + + + + + + JS annotation test + + + + + + + + + + + + + + + + +
    +

    Javascript annotation service test

    +
    + +

    Current Connectivity:

    + +
    +

    Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.

    + +

    Header Level 2

    + +
      +
    1. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
    2. +
    3. Aliquam tincidunt mauris eu risus.
    4. +
    + +

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est.

    + +

    Header Level 3

    + +
      +
    • Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
    • +
    • Aliquam tincidunt mauris eu risus.
    • +
    + +
    
    +      #header h1 a {
    +        display: block;
    +        width: 300px;
    +        height: 80px;
    +      }
    +      
    + +

    + 如是我闻。一时佛在室罗筏城,只桓精舍。与大比丘众,千二百五十人俱。皆是无漏大阿罗汉。佛子住持,善超诸有。能于国土,成就威仪。从佛转轮,妙堪遗嘱。严净毗尼,弘范三界。应身无量,度脱众生。拔济未来,越诸尘累。其名曰。大智舍利弗。摩诃目犍连。摩诃拘絺罗。富楼那弥多罗尼子。须菩提。优波尼沙陀等。而为上首。复有无量辟支无学。并其初心。同来佛所。属诸比丘休夏自恣。十方菩萨咨决心疑。钦奉慈严将求密义。即时如来敷座宴安。为诸会中,宣示深奥。法筵清众,得未曾有。迦陵仙音,遍十方界。恒沙菩萨,来聚道场。文殊师利而为上首。 + + + + 时波斯匿王,为其父王讳日营斋。请佛宫掖。自迎如来。广设珍羞无上妙味。兼复亲延诸大菩萨。城中复有长者居士同时饭僧。伫佛来应。佛敕大殊,分领菩萨及阿罗汉,应诸斋主。唯有阿难,先受别请。远游未还,不遑僧次。既无上座,及阿阇黎。途中独归。其日无供。即时阿难,执持应器,于所游城,次第循乞。心中初求最后檀越,以为斋主。无问净秽,刹利尊姓。及旃陀罗。方行等慈,不择微贱。发意圆成,一切众生,无量功德。阿难已知如来世尊,诃须菩提,及大迦叶,为阿罗汉,心不均平。钦仰如来,开阐无遮,度诸疑谤。经彼城隍,徐步郭门。严整威仪,肃恭斋法。尔时阿难,因乞食次,经历淫室,遭大幻术。摩登伽女,以娑毗迦罗先梵天咒,摄入淫席。淫躬抚摩,将毁戒体。 + + + + 如来知彼淫术所加,斋毕旋归。王及大臣长者居士,俱来随佛,愿闻法要。于时世尊。顶放百宝无畏光明,光中出生千叶宝莲,有佛化身,结跏趺坐,宣说神咒。敕文殊师利将咒往护。恶咒消灭。提奖阿难,及摩登伽,归来佛所。阿难见佛。顶礼悲泣。恨无始来。一向多闻,未全道力。殷勤启请,十方如来得成菩提,妙奢摩他,三摩,禅那,最初方便。于时复有恒沙菩萨。及诸十方大阿罗汉。辟支佛等。俱愿乐闻。退坐默然。承受圣旨。 + + + + 佛告阿难。汝我同气,情均天伦。当初发心,于我法中,见何胜相,顿舍世间深重恩爱。阿难白佛我见如来三十二相。胜妙殊绝。形体映彻犹如琉璃。常自思惟,此相非是欲爱所生。何以故。欲气粗浊,腥臊交遘,脓血杂乱,不能发生胜净妙明紫金光聚。是以渴仰,从佛剃落。佛言:善哉阿难。汝等当知一切众生,从无始来。生死相续,皆由不知常住真心性净明体。用诸妄想。此想不真,故有轮转。汝今欲研无上菩提真发明性。应当直心詶我所问。十方如来同一道故,出离生死,皆以直心。心言直故,如是乃至终始地位,中间永无诸委曲相。 + +

    +
    + + + + + + diff --git a/src/dictionary.coffee b/src/dictionary.coffee new file mode 100644 index 000000000..2fa8b80ef --- /dev/null +++ b/src/dictionary.coffee @@ -0,0 +1,376 @@ +# Public: Creates an element for dictionary. +class Annotator.Dictionary extends Annotator.Widget + + # Events to be bound to @element. + events: + ".annotator-cancel click": "hide" + ".annotator-cancel mouseover": "onCancelButtonMouseover" + + # Classes to toggle state. + classes: + hide: 'annotator-hide' + focus: 'annotator-focus' + + # HTML template for @element. + html: """ +
    +
    +
    + 123 +
    + +
    +
    + """ + + options: {} # Configuration options + + # Public: Creates an instance of the Dictionary object. This will create the + # @element from the @html string and set up all events. + # + # options - An Object literal containing options. There are currently no + # options implemented. + # + # Examples + # + # # Creates a new dictionary, adds a custom field and + # # loads an annotation for editing. + # dictionary = new Annotator.Dictionary + # dictionary.addField({ + # parameter: 'word' + # }) + # dictionary.load(annotation) + # + # Returns a new Dictionary instance. + constructor: (options) -> + super $(@html)[0], options + + @fields = [] + @annotation = {} + + # Public: Displays the Dictionary and fires a "show" event. + # Can be used as an event callback and will call Event#preventDefault() + # on the supplied event. + # + # event - Event object provided if method is called by event + # listener (default:undefined) + # + # Examples + # + # # Displays the dictionary. + # dictionary.show() + # + # # Displays the dictionary on click (prevents default action). + # $('a.show-dictionary').bind('click', dictionary.show) + # + # Returns itself. + show: (event) => + Annotator.Util.preventEventDefault event + + @element.removeClass(@classes.hide) + + # invert if necessary + this.checkOrientation() + + # give main textarea focus + @element.find(":input:first").focus() + + this.setupDraggables() + + this.publish('show') + + + # Public: Hides the Dictionary and fires a "hide" event. Can be used as an event + # callback and will call Event#preventDefault() on the supplied event. + # + # event - Event object provided if method is called by event + # listener (default:undefined) + # + # Examples + # + # # Hides the dictionary. + # dictionary.hide() + # + # # Hide the dictionary on click (prevents default action). + # $('a.hide-dictionary').bind('click', dictionary.hide) + # + # Returns itself. + hide: (event) => + Annotator.Util.preventEventDefault event + + @element.addClass(@classes.hide) + this.publish('hide') + + # Public: Loads an annotation into the Editor and displays it setting + # Editor#annotation to the provided annotation. It fires the "load" event + # providing the current annotation subscribers can modify the annotation + # before it updates the editor fields. + # + # annotation - An annotation Object to display for editing. + # + # Examples + # + # # Diplays the editor with the annotation loaded. + # editor.load({text: 'My Annotation'}) + # + # editor.on('load', (annotation) -> + # console.log annotation.text + # ).load({text: 'My Annotation'}) + # # => Outputs "My Annotation" + # + # Returns itself. + load: (annotation) => + @annotation = annotation + + this.publish('load', [@annotation]) + + for field in @fields + field.load(field.element, @annotation) + + this.show() + + # Public: Hides the Editor and passes the annotation to all registered fields + # so they can update its state. It then fires the "save" event so that other + # parties can further modify the annotation. + # Can be used as an event callback and will call Event#preventDefault() on the + # supplied event. + # + # event - Event object provided if method is called by event + # listener (default:undefined) + # + # Examples + # + # # Submits the editor. + # editor.submit() + # + # # Submits the editor on click (prevents default action). + # $('button.submit-editor').bind('click', editor.submit) + # + # # Appends "Comment: " to the annotation comment text. + # editor.on('save', (annotation) -> + # annotation.text = "Comment: " + annotation.text + # ).submit() + # + # Returns itself. + submit: (event) => + Annotator.Util.preventEventDefault event + + for field in @fields + field.submit(field.element, @annotation) + + this.publish('save', [@annotation]) + + this.hide() + + # Public: Adds an addional form field to the editor. Callbacks can be provided + # to update the view and anotations on load and submission. + # + # options - An options Object. Options are as follows: + # id - A unique id for the form element will also be set as the + # "for" attrubute of a label if there is one. Defaults to + # a timestamp. (default: "annotator-field-{timestamp}") + # type - Input type String. One of "input", "textarea", + # "checkbox", "select" (default: "input") + # label - Label to display either in a label Element or as place- + # holder text depending on the type. (default: "") + # load - Callback Function called when the editor is loaded with a + # new annotation. Recieves the field
  • element and the + # annotation to be loaded. + # submit - Callback Function called when the editor is submitted. + # Recieves the field
  • element and the annotation to be + # updated. + # + # Examples + # + # # Add a new input element. + # editor.addField({ + # label: "Tags", + # + # # This is called when the editor is loaded use it to update your input. + # load: (field, annotation) -> + # # Do something with the annotation. + # value = getTagString(annotation.tags) + # $(field).find('input').val(value) + # + # # This is called when the editor is submitted use it to retrieve data + # # from your input and save it to the annotation. + # submit: (field, annotation) -> + # value = $(field).find('input').val() + # annotation.tags = getTagsFromString(value) + # }) + # + # # Add a new checkbox element. + # editor.addField({ + # type: 'checkbox', + # id: 'annotator-field-my-checkbox', + # label: 'Allow anyone to see this annotation', + # load: (field, annotation) -> + # # Check what state of input should be. + # if checked + # $(field).find('input').attr('checked', 'checked') + # else + # $(field).find('input').removeAttr('checked') + + # submit: (field, annotation) -> + # checked = $(field).find('input').is(':checked') + # # Do something. + # }) + # + # Returns the created
  • Element. + addField: (options) -> + field = $.extend({ + id: 'annotator-field-' + Annotator.Util.uuid() + type: 'input' + label: '' + load: -> + submit: -> + }, options) + + input = null + element = $('
  • ') + field.element = element[0] + + switch (field.type) + when 'textarea' then input = $('