spiderfw 0.6.38 → 0.6.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +13 -5
- data/CHANGELOG +23 -0
- data/VERSION +1 -1
- data/apps/core/admin/views/admin.layout.shtml +6 -0
- data/apps/core/auth/controllers/login_controller.rb +1 -1
- data/apps/core/components/assets.rb +55 -6
- data/apps/core/components/public/bootstrap/scss/_variables.scss +5 -2
- data/apps/core/components/public/bootstrap/scss/bootstrap.css +942 -236
- data/apps/core/components/public/bootstrap/scss/responsive.css +187 -30
- data/apps/core/components/public/css/tinymce/skins/lightgray/AbsoluteLayout.less +17 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Animations.less +10 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Button.less +172 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/ButtonGroup.less +71 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Checkbox.less +49 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/ColorBox.less +6 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/ColorButton.less +72 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/ColorPicker.less +80 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/ComboBox.less +39 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Container.less +9 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Content.Inline.less +4 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Content.Objects.less +166 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Content.less +27 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/CropRect.less +54 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/FieldSet.less +15 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/FitLayout.less +9 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/FloatPanel.less +69 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/FlowLayout.less +36 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Icons.Ie7.less +136 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Icons.less +180 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Iframe.less +6 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/ImagePanel.less +20 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/InfoBox.less +71 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Label.less +38 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/ListBox.less +26 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Menu.less +34 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/MenuBar.less +32 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/MenuButton.less +34 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/MenuItem.less +142 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Mixins.less +54 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Notification.less +144 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Panel.less +7 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Path.less +45 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Progress.less +34 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Radio.less +1 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Reset.less +32 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/ResizeHandle.less +18 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Scrollable.less +44 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/SelectBox.less +6 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Slider.less +29 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Spacer.less +5 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/SplitButton.less +49 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/StackLayout.less +5 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/TabPanel.less +44 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/TextBox.less +41 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Throbber.less +19 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/TinyMCE.less +159 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/ToolTip.less +129 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Variables.less +214 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/Window.less +127 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/content.inline.min.css +1 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/content.min.css +1 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/fonts/readme.md +1 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/fonts/tinymce-small.eot +0 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/fonts/tinymce-small.json +1277 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/fonts/tinymce-small.svg +63 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/fonts/tinymce-small.ttf +0 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/fonts/tinymce-small.woff +0 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/fonts/tinymce.eot +0 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/fonts/tinymce.json +3381 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/fonts/tinymce.svg +129 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/fonts/tinymce.ttf +0 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/fonts/tinymce.woff +0 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/img/anchor.gif +0 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/img/loader.gif +0 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/img/object.gif +0 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/img/trans.gif +0 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/skin.dev.less +46 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/skin.ie7.dev.less +46 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/skin.ie7.less +2542 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/skin.ie7.min.css +1 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/skin.less +2586 -0
- data/apps/core/components/public/css/tinymce/skins/lightgray/skin.min.css +1 -0
- data/apps/core/components/public/js/bootbox_2/bootbox.js +551 -0
- data/apps/core/components/public/js/jquery/jquery-ui-1.9.2/ui/i18n/jquery.ui.datepicker-it-min.js +4 -0
- data/apps/core/components/public/js/spider.js +7 -3
- data/apps/core/components/public/js/tinymce/classes/AddOnManager.js +265 -0
- data/apps/core/components/public/js/tinymce/classes/Compat.js +90 -0
- data/apps/core/components/public/js/tinymce/classes/DragDropOverrides.js +224 -0
- data/apps/core/components/public/js/tinymce/classes/Editor.js +2221 -0
- data/apps/core/components/public/js/tinymce/classes/EditorCommands.js +1028 -0
- data/apps/core/components/public/js/tinymce/classes/EditorManager.js +715 -0
- data/apps/core/components/public/js/tinymce/classes/EditorObservable.js +204 -0
- data/apps/core/components/public/js/tinymce/classes/EditorUpload.js +191 -0
- data/apps/core/components/public/js/tinymce/classes/EnterKey.js +676 -0
- data/apps/core/components/public/js/tinymce/classes/Env.js +177 -0
- data/apps/core/components/public/js/tinymce/classes/FocusManager.js +266 -0
- data/apps/core/components/public/js/tinymce/classes/ForceBlocks.js +138 -0
- data/apps/core/components/public/js/tinymce/classes/Formatter.js +2378 -0
- data/apps/core/components/public/js/tinymce/classes/LegacyInput.js +82 -0
- data/apps/core/components/public/js/tinymce/classes/Mode.js +54 -0
- data/apps/core/components/public/js/tinymce/classes/NodeChange.js +154 -0
- data/apps/core/components/public/js/tinymce/classes/NotificationManager.js +156 -0
- data/apps/core/components/public/js/tinymce/classes/Register.js +34 -0
- data/apps/core/components/public/js/tinymce/classes/SelectionOverrides.js +810 -0
- data/apps/core/components/public/js/tinymce/classes/Shortcuts.js +172 -0
- data/apps/core/components/public/js/tinymce/classes/UndoManager.js +346 -0
- data/apps/core/components/public/js/tinymce/classes/WindowManager.js +278 -0
- data/apps/core/components/public/js/tinymce/classes/caret/CaretBookmark.js +263 -0
- data/apps/core/components/public/js/tinymce/classes/caret/CaretCandidate.js +86 -0
- data/apps/core/components/public/js/tinymce/classes/caret/CaretContainer.js +151 -0
- data/apps/core/components/public/js/tinymce/classes/caret/CaretPosition.js +371 -0
- data/apps/core/components/public/js/tinymce/classes/caret/CaretUtils.js +302 -0
- data/apps/core/components/public/js/tinymce/classes/caret/CaretWalker.js +215 -0
- data/apps/core/components/public/js/tinymce/classes/caret/FakeCaret.js +192 -0
- data/apps/core/components/public/js/tinymce/classes/caret/LineUtils.js +135 -0
- data/apps/core/components/public/js/tinymce/classes/caret/LineWalker.js +166 -0
- data/apps/core/components/public/js/tinymce/classes/data/Binding.js +79 -0
- data/apps/core/components/public/js/tinymce/classes/data/ObservableArray.js +196 -0
- data/apps/core/components/public/js/tinymce/classes/data/ObservableObject.js +194 -0
- data/apps/core/components/public/js/tinymce/classes/dom/BookmarkManager.js +456 -0
- data/apps/core/components/public/js/tinymce/classes/dom/ControlSelection.js +634 -0
- data/apps/core/components/public/js/tinymce/classes/dom/DOMUtils.js +1853 -0
- data/apps/core/components/public/js/tinymce/classes/dom/Dimensions.js +64 -0
- data/apps/core/components/public/js/tinymce/classes/dom/DomQuery.js +1578 -0
- data/apps/core/components/public/js/tinymce/classes/dom/ElementUtils.js +118 -0
- data/apps/core/components/public/js/tinymce/classes/dom/EventUtils.js +583 -0
- data/apps/core/components/public/js/tinymce/classes/dom/NodePath.js +50 -0
- data/apps/core/components/public/js/tinymce/classes/dom/NodeType.js +110 -0
- data/apps/core/components/public/js/tinymce/classes/dom/Range.js +785 -0
- data/apps/core/components/public/js/tinymce/classes/dom/RangeUtils.js +628 -0
- data/apps/core/components/public/js/tinymce/classes/dom/ScriptLoader.js +254 -0
- data/apps/core/components/public/js/tinymce/classes/dom/Selection.js +1008 -0
- data/apps/core/components/public/js/tinymce/classes/dom/Serializer.js +506 -0
- data/apps/core/components/public/js/tinymce/classes/dom/Sizzle.jQuery.js +23 -0
- data/apps/core/components/public/js/tinymce/classes/dom/Sizzle.js +2039 -0
- data/apps/core/components/public/js/tinymce/classes/dom/StyleSheetLoader.js +190 -0
- data/apps/core/components/public/js/tinymce/classes/dom/TreeWalker.js +127 -0
- data/apps/core/components/public/js/tinymce/classes/dom/TridentSelection.js +508 -0
- data/apps/core/components/public/js/tinymce/classes/file/BlobCache.js +72 -0
- data/apps/core/components/public/js/tinymce/classes/file/Conversions.js +106 -0
- data/apps/core/components/public/js/tinymce/classes/file/ImageScanner.js +145 -0
- data/apps/core/components/public/js/tinymce/classes/file/Uploader.js +193 -0
- data/apps/core/components/public/js/tinymce/classes/fmt/Hooks.js +66 -0
- data/apps/core/components/public/js/tinymce/classes/fmt/Preview.js +151 -0
- data/apps/core/components/public/js/tinymce/classes/geom/ClientRect.js +136 -0
- data/apps/core/components/public/js/tinymce/classes/geom/Rect.js +214 -0
- data/apps/core/components/public/js/tinymce/classes/html/DomParser.js +822 -0
- data/apps/core/components/public/js/tinymce/classes/html/Entities.js +268 -0
- data/apps/core/components/public/js/tinymce/classes/html/Node.js +496 -0
- data/apps/core/components/public/js/tinymce/classes/html/SaxParser.js +474 -0
- data/apps/core/components/public/js/tinymce/classes/html/Schema.js +1004 -0
- data/apps/core/components/public/js/tinymce/classes/html/Serializer.js +158 -0
- data/apps/core/components/public/js/tinymce/classes/html/Styles.js +363 -0
- data/apps/core/components/public/js/tinymce/classes/html/Writer.js +199 -0
- data/apps/core/components/public/js/tinymce/classes/jquery.tinymce.js +377 -0
- data/apps/core/components/public/js/tinymce/classes/text/ExtendingChar.js +53 -0
- data/apps/core/components/public/js/tinymce/classes/text/Zwsp.js +36 -0
- data/apps/core/components/public/js/tinymce/classes/ui/AbsoluteLayout.js +63 -0
- data/apps/core/components/public/js/tinymce/classes/ui/BoxUtils.js +98 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Button.js +199 -0
- data/apps/core/components/public/js/tinymce/classes/ui/ButtonGroup.js +62 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Checkbox.js +162 -0
- data/apps/core/components/public/js/tinymce/classes/ui/ClassList.js +149 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Collection.js +438 -0
- data/apps/core/components/public/js/tinymce/classes/ui/ColorBox.js +72 -0
- data/apps/core/components/public/js/tinymce/classes/ui/ColorButton.js +124 -0
- data/apps/core/components/public/js/tinymce/classes/ui/ColorPicker.js +206 -0
- data/apps/core/components/public/js/tinymce/classes/ui/ComboBox.js +306 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Container.js +506 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Control.js +1301 -0
- data/apps/core/components/public/js/tinymce/classes/ui/DomUtils.js +107 -0
- data/apps/core/components/public/js/tinymce/classes/ui/DragHelper.js +144 -0
- data/apps/core/components/public/js/tinymce/classes/ui/ElementPath.js +79 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Factory.js +105 -0
- data/apps/core/components/public/js/tinymce/classes/ui/FieldSet.js +59 -0
- data/apps/core/components/public/js/tinymce/classes/ui/FilePicker.js +85 -0
- data/apps/core/components/public/js/tinymce/classes/ui/FitLayout.js +48 -0
- data/apps/core/components/public/js/tinymce/classes/ui/FlexLayout.js +246 -0
- data/apps/core/components/public/js/tinymce/classes/ui/FloatPanel.js +409 -0
- data/apps/core/components/public/js/tinymce/classes/ui/FlowLayout.js +46 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Form.js +157 -0
- data/apps/core/components/public/js/tinymce/classes/ui/FormItem.js +56 -0
- data/apps/core/components/public/js/tinymce/classes/ui/FormatControls.js +535 -0
- data/apps/core/components/public/js/tinymce/classes/ui/GridLayout.js +233 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Iframe.js +85 -0
- data/apps/core/components/public/js/tinymce/classes/ui/InfoBox.js +93 -0
- data/apps/core/components/public/js/tinymce/classes/ui/KeyboardNavigation.js +406 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Label.js +144 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Layout.js +120 -0
- data/apps/core/components/public/js/tinymce/classes/ui/ListBox.js +152 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Menu.js +195 -0
- data/apps/core/components/public/js/tinymce/classes/ui/MenuBar.js +33 -0
- data/apps/core/components/public/js/tinymce/classes/ui/MenuButton.js +268 -0
- data/apps/core/components/public/js/tinymce/classes/ui/MenuItem.js +336 -0
- data/apps/core/components/public/js/tinymce/classes/ui/MessageBox.js +202 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Movable.js +200 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Notification.js +154 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Panel.js +67 -0
- data/apps/core/components/public/js/tinymce/classes/ui/PanelButton.js +114 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Path.js +127 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Progress.js +81 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Radio.js +29 -0
- data/apps/core/components/public/js/tinymce/classes/ui/ReflowQueue.js +79 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Resizable.js +68 -0
- data/apps/core/components/public/js/tinymce/classes/ui/ResizeHandle.js +86 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Scrollable.js +141 -0
- data/apps/core/components/public/js/tinymce/classes/ui/SelectBox.js +106 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Selector.js +369 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Slider.js +161 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Spacer.js +39 -0
- data/apps/core/components/public/js/tinymce/classes/ui/SplitButton.js +146 -0
- data/apps/core/components/public/js/tinymce/classes/ui/StackLayout.js +34 -0
- data/apps/core/components/public/js/tinymce/classes/ui/TabPanel.js +178 -0
- data/apps/core/components/public/js/tinymce/classes/ui/TextBox.js +208 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Throbber.js +88 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Toolbar.js +56 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Tooltip.js +73 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Widget.js +151 -0
- data/apps/core/components/public/js/tinymce/classes/ui/Window.js +474 -0
- data/apps/core/components/public/js/tinymce/classes/util/Arr.js +153 -0
- data/apps/core/components/public/js/tinymce/classes/util/Class.js +167 -0
- data/apps/core/components/public/js/tinymce/classes/util/Color.js +235 -0
- data/apps/core/components/public/js/tinymce/classes/util/Delay.js +191 -0
- data/apps/core/components/public/js/tinymce/classes/util/EventDispatcher.js +294 -0
- data/apps/core/components/public/js/tinymce/classes/util/Fun.js +87 -0
- data/apps/core/components/public/js/tinymce/classes/util/I18n.js +116 -0
- data/apps/core/components/public/js/tinymce/classes/util/JSON.js +109 -0
- data/apps/core/components/public/js/tinymce/classes/util/JSONP.js +38 -0
- data/apps/core/components/public/js/tinymce/classes/util/JSONRequest.js +110 -0
- data/apps/core/components/public/js/tinymce/classes/util/LocalStorage.js +213 -0
- data/apps/core/components/public/js/tinymce/classes/util/Observable.js +129 -0
- data/apps/core/components/public/js/tinymce/classes/util/Promise.js +200 -0
- data/apps/core/components/public/js/tinymce/classes/util/Quirks.js +1701 -0
- data/apps/core/components/public/js/tinymce/classes/util/Tools.js +442 -0
- data/apps/core/components/public/js/tinymce/classes/util/URI.js +411 -0
- data/apps/core/components/public/js/tinymce/classes/util/VK.js +37 -0
- data/apps/core/components/public/js/tinymce/classes/util/XHR.js +110 -0
- data/apps/core/components/public/js/tinymce/jquery.tinymce.min.js +1 -0
- data/apps/core/components/public/js/tinymce/langs/it.js +219 -0
- data/apps/core/components/public/js/tinymce/langs/readme.md +3 -0
- data/apps/core/components/public/js/tinymce/license.txt +504 -0
- data/apps/core/components/public/js/tinymce/plugins/advlist/plugin.js +97 -0
- data/apps/core/components/public/js/tinymce/plugins/advlist/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/anchor/plugin.js +55 -0
- data/apps/core/components/public/js/tinymce/plugins/anchor/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/autolink/plugin.js +204 -0
- data/apps/core/components/public/js/tinymce/plugins/autolink/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/autoresize/plugin.js +162 -0
- data/apps/core/components/public/js/tinymce/plugins/autoresize/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/autosave/plugin.js +165 -0
- data/apps/core/components/public/js/tinymce/plugins/autosave/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/bbcode/plugin.js +123 -0
- data/apps/core/components/public/js/tinymce/plugins/bbcode/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/charmap/plugin.js +450 -0
- data/apps/core/components/public/js/tinymce/plugins/charmap/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/code/plugin.js +60 -0
- data/apps/core/components/public/js/tinymce/plugins/code/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/codesample/classes/Dialog.js +121 -0
- data/apps/core/components/public/js/tinymce/plugins/codesample/classes/Plugin.js +95 -0
- data/apps/core/components/public/js/tinymce/plugins/codesample/classes/Prism.js +937 -0
- data/apps/core/components/public/js/tinymce/plugins/codesample/classes/Utils.js +33 -0
- data/apps/core/components/public/js/tinymce/plugins/codesample/css/prism.css +138 -0
- data/apps/core/components/public/js/tinymce/plugins/codesample/plugin.dev.js +141 -0
- data/apps/core/components/public/js/tinymce/plugins/codesample/plugin.js +1299 -0
- data/apps/core/components/public/js/tinymce/plugins/codesample/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/colorpicker/plugin.js +112 -0
- data/apps/core/components/public/js/tinymce/plugins/colorpicker/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/compat3x/css/dialog.css +118 -0
- data/apps/core/components/public/js/tinymce/plugins/compat3x/img/buttons.png +0 -0
- data/apps/core/components/public/js/tinymce/plugins/compat3x/img/icons.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/compat3x/img/items.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/compat3x/img/menu_arrow.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/compat3x/img/menu_check.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/compat3x/img/progress.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/compat3x/img/tabs.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/compat3x/plugin.js +297 -0
- data/apps/core/components/public/js/tinymce/plugins/compat3x/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/compat3x/tiny_mce_popup.js +542 -0
- data/apps/core/components/public/js/tinymce/plugins/compat3x/utils/editable_selects.js +70 -0
- data/apps/core/components/public/js/tinymce/plugins/compat3x/utils/form_utils.js +210 -0
- data/apps/core/components/public/js/tinymce/plugins/compat3x/utils/mctabs.js +164 -0
- data/apps/core/components/public/js/tinymce/plugins/compat3x/utils/validate.js +252 -0
- data/apps/core/components/public/js/tinymce/plugins/contextmenu/plugin.js +88 -0
- data/apps/core/components/public/js/tinymce/plugins/contextmenu/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/directionality/plugin.js +64 -0
- data/apps/core/components/public/js/tinymce/plugins/directionality/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/emoticons/img/smiley-cool.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/emoticons/img/smiley-cry.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/emoticons/img/smiley-embarassed.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/emoticons/img/smiley-foot-in-mouth.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/emoticons/img/smiley-frown.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/emoticons/img/smiley-innocent.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/emoticons/img/smiley-kiss.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/emoticons/img/smiley-laughing.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/emoticons/img/smiley-money-mouth.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/emoticons/img/smiley-sealed.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/emoticons/img/smiley-smile.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/emoticons/img/smiley-surprised.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/emoticons/img/smiley-tongue-out.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/emoticons/img/smiley-undecided.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/emoticons/img/smiley-wink.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/emoticons/img/smiley-yell.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/emoticons/plugin.js +65 -0
- data/apps/core/components/public/js/tinymce/plugins/emoticons/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/example/dialog.html +8 -0
- data/apps/core/components/public/js/tinymce/plugins/example/plugin.js +68 -0
- data/apps/core/components/public/js/tinymce/plugins/example/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/example_dependency/plugin.js +22 -0
- data/apps/core/components/public/js/tinymce/plugins/example_dependency/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/fullpage/plugin.js +490 -0
- data/apps/core/components/public/js/tinymce/plugins/fullpage/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/fullscreen/plugin.js +154 -0
- data/apps/core/components/public/js/tinymce/plugins/fullscreen/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/hr/plugin.js +30 -0
- data/apps/core/components/public/js/tinymce/plugins/hr/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/image/plugin.js +630 -0
- data/apps/core/components/public/js/tinymce/plugins/image/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/imagetools/config/bolt/atomic.js +6 -0
- data/apps/core/components/public/js/tinymce/plugins/imagetools/config/bolt/browser.js +6 -0
- data/apps/core/components/public/js/tinymce/plugins/imagetools/config/bolt/demo.js +8 -0
- data/apps/core/components/public/js/tinymce/plugins/imagetools/config/bolt/prod.js +6 -0
- data/apps/core/components/public/js/tinymce/plugins/imagetools/plugin.js +2668 -0
- data/apps/core/components/public/js/tinymce/plugins/imagetools/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/imagetools/src/demo/html/demo.html +16 -0
- data/apps/core/components/public/js/tinymce/plugins/imagetools/src/demo/js/Demo.js +92 -0
- data/apps/core/components/public/js/tinymce/plugins/imagetools/src/main/js/CropRect.js +214 -0
- data/apps/core/components/public/js/tinymce/plugins/imagetools/src/main/js/Dialog.js +485 -0
- data/apps/core/components/public/js/tinymce/plugins/imagetools/src/main/js/ImagePanel.js +218 -0
- data/apps/core/components/public/js/tinymce/plugins/imagetools/src/main/js/Plugin.js +411 -0
- data/apps/core/components/public/js/tinymce/plugins/imagetools/src/main/js/UndoStack.js +57 -0
- data/apps/core/components/public/js/tinymce/plugins/importcss/plugin.js +227 -0
- data/apps/core/components/public/js/tinymce/plugins/importcss/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/insertdatetime/plugin.js +121 -0
- data/apps/core/components/public/js/tinymce/plugins/insertdatetime/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/layer/plugin.js +225 -0
- data/apps/core/components/public/js/tinymce/plugins/layer/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/legacyoutput/plugin.js +211 -0
- data/apps/core/components/public/js/tinymce/plugins/legacyoutput/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/link/plugin.js +403 -0
- data/apps/core/components/public/js/tinymce/plugins/link/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/lists/plugin.js +885 -0
- data/apps/core/components/public/js/tinymce/plugins/lists/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/media/moxieplayer.swf +0 -0
- data/apps/core/components/public/js/tinymce/plugins/media/plugin.js +878 -0
- data/apps/core/components/public/js/tinymce/plugins/media/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/nonbreaking/plugin.js +53 -0
- data/apps/core/components/public/js/tinymce/plugins/nonbreaking/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/noneditable/plugin.js +101 -0
- data/apps/core/components/public/js/tinymce/plugins/noneditable/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/pagebreak/plugin.js +88 -0
- data/apps/core/components/public/js/tinymce/plugins/pagebreak/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/paste/classes/Clipboard.js +672 -0
- data/apps/core/components/public/js/tinymce/plugins/paste/classes/Plugin.js +121 -0
- data/apps/core/components/public/js/tinymce/plugins/paste/classes/Quirks.js +159 -0
- data/apps/core/components/public/js/tinymce/plugins/paste/classes/Utils.js +140 -0
- data/apps/core/components/public/js/tinymce/plugins/paste/classes/WordFilter.js +500 -0
- data/apps/core/components/public/js/tinymce/plugins/paste/plugin.dev.js +142 -0
- data/apps/core/components/public/js/tinymce/plugins/paste/plugin.js +1708 -0
- data/apps/core/components/public/js/tinymce/plugins/paste/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/preview/plugin.js +88 -0
- data/apps/core/components/public/js/tinymce/plugins/preview/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/print/plugin.js +32 -0
- data/apps/core/components/public/js/tinymce/plugins/print/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/save/plugin.js +98 -0
- data/apps/core/components/public/js/tinymce/plugins/save/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/searchreplace/plugin.js +609 -0
- data/apps/core/components/public/js/tinymce/plugins/searchreplace/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/spellchecker/classes/DomTextMatcher.js +480 -0
- data/apps/core/components/public/js/tinymce/plugins/spellchecker/classes/Plugin.js +439 -0
- data/apps/core/components/public/js/tinymce/plugins/spellchecker/plugin.dev.js +139 -0
- data/apps/core/components/public/js/tinymce/plugins/spellchecker/plugin.js +1026 -0
- data/apps/core/components/public/js/tinymce/plugins/spellchecker/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/tabfocus/plugin.js +120 -0
- data/apps/core/components/public/js/tinymce/plugins/tabfocus/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/table/classes/CellSelection.js +202 -0
- data/apps/core/components/public/js/tinymce/plugins/table/classes/Dialogs.js +824 -0
- data/apps/core/components/public/js/tinymce/plugins/table/classes/Plugin.js +599 -0
- data/apps/core/components/public/js/tinymce/plugins/table/classes/Quirks.js +400 -0
- data/apps/core/components/public/js/tinymce/plugins/table/classes/ResizeBars.js +984 -0
- data/apps/core/components/public/js/tinymce/plugins/table/classes/TableGrid.js +941 -0
- data/apps/core/components/public/js/tinymce/plugins/table/classes/Utils.js +36 -0
- data/apps/core/components/public/js/tinymce/plugins/table/plugin.dev.js +142 -0
- data/apps/core/components/public/js/tinymce/plugins/table/plugin.js +4106 -0
- data/apps/core/components/public/js/tinymce/plugins/table/plugin.min.js +2 -0
- data/apps/core/components/public/js/tinymce/plugins/template/plugin.js +270 -0
- data/apps/core/components/public/js/tinymce/plugins/template/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/textcolor/plugin.js +282 -0
- data/apps/core/components/public/js/tinymce/plugins/textcolor/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/textpattern/plugin.js +268 -0
- data/apps/core/components/public/js/tinymce/plugins/textpattern/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/css/visualblocks.css +135 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/img/address.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/img/article.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/img/aside.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/img/blockquote.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/img/div.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/img/dl.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/img/figure.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/img/h1.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/img/h2.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/img/h3.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/img/h4.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/img/h5.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/img/h6.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/img/hgroup.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/img/ol.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/img/p.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/img/pre.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/img/section.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/img/ul.gif +0 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/plugin.js +86 -0
- data/apps/core/components/public/js/tinymce/plugins/visualblocks/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/visualchars/plugin.js +123 -0
- data/apps/core/components/public/js/tinymce/plugins/visualchars/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/plugins/wordcount/plugin.js +69 -0
- data/apps/core/components/public/js/tinymce/plugins/wordcount/plugin.min.js +1 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/AbsoluteLayout.less +17 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Animations.less +10 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Button.less +172 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/ButtonGroup.less +71 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Checkbox.less +49 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/ColorBox.less +6 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/ColorButton.less +72 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/ColorPicker.less +80 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/ComboBox.less +39 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Container.less +9 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Content.Inline.less +4 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Content.Objects.less +166 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Content.less +27 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/CropRect.less +54 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/FieldSet.less +15 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/FitLayout.less +9 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/FloatPanel.less +69 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/FlowLayout.less +36 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Icons.Ie7.less +136 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Icons.less +180 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Iframe.less +6 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/ImagePanel.less +20 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/InfoBox.less +71 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Label.less +38 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/ListBox.less +26 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Menu.less +34 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/MenuBar.less +32 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/MenuButton.less +34 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/MenuItem.less +142 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Mixins.less +54 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Notification.less +144 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Panel.less +7 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Path.less +45 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Progress.less +34 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Radio.less +1 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Reset.less +32 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/ResizeHandle.less +18 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Scrollable.less +44 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/SelectBox.less +6 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Slider.less +29 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Spacer.less +5 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/SplitButton.less +49 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/StackLayout.less +5 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/TabPanel.less +44 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/TextBox.less +41 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Throbber.less +19 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/TinyMCE.less +159 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/ToolTip.less +129 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Variables.less +214 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/Window.less +127 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/content.inline.min.css +1 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/content.min.css +1 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/fonts/readme.md +1 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/fonts/tinymce-small.eot +0 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/fonts/tinymce-small.json +1277 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/fonts/tinymce-small.svg +63 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/fonts/tinymce-small.ttf +0 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/fonts/tinymce-small.woff +0 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/fonts/tinymce.eot +0 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/fonts/tinymce.json +3381 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/fonts/tinymce.svg +129 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/fonts/tinymce.ttf +0 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/fonts/tinymce.woff +0 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/img/anchor.gif +0 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/img/loader.gif +0 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/img/object.gif +0 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/img/trans.gif +0 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/skin.dev.less +46 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/skin.ie7.dev.less +46 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/skin.ie7.less +2542 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/skin.ie7.min.css +1 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/skin.less +2586 -0
- data/apps/core/components/public/js/tinymce/skins/lightgray/skin.min.css +1 -0
- data/apps/core/components/public/js/tinymce/themes/modern/theme.js +878 -0
- data/apps/core/components/public/js/tinymce/themes/modern/theme.min.js +1 -0
- data/apps/core/components/public/js/tinymce/tinymce.dev.js +286 -0
- data/apps/core/components/public/js/tinymce/tinymce.js +45811 -0
- data/apps/core/components/public/js/tinymce/tinymce.min.js +13 -0
- data/apps/core/forms/widgets/form/form.rb +3 -1
- data/apps/core/forms/widgets/form/form.shtml +1 -0
- data/apps/core/forms/widgets/inputs/search_select/search_select.rb +1 -1
- data/apps/core/forms/widgets/inputs/select/select.rb +1 -1
- data/apps/core/forms/widgets/inputs/select/select.shtml +0 -1
- data/apps/messenger/backends/sms/skebby.rb +1 -1
- data/apps/messenger/controllers/mixins/messenger_helper.rb +23 -5
- data/lib/spiderfw/config/options/spider.rb +1 -1
- data/lib/spiderfw/controller/mixins/visual.rb +2 -0
- data/lib/spiderfw/http/adapters/rack.rb +10 -5
- data/lib/spiderfw/http/http.rb +4 -2
- data/lib/spiderfw/model/base_model.rb +4 -4
- data/lib/spiderfw/model/mappers/db_mapper.rb +4 -2
- data/lib/spiderfw/model/storage/db/adapters/mysql.rb +2 -1
- data/lib/spiderfw/model/storage/db/db_storage.rb +4 -0
- data/lib/spiderfw/spider.rb +6 -0
- data/lib/spiderfw/templates/layout.rb +1 -1
- data/lib/spiderfw/utils/monkey/object.rb +3 -0
- data/spider.gemspec +6 -2
- metadata +539 -42
- data/blueprints/.DS_Store +0 -0
@@ -0,0 +1,254 @@
|
|
1
|
+
/**
|
2
|
+
* ScriptLoader.js
|
3
|
+
*
|
4
|
+
* Released under LGPL License.
|
5
|
+
* Copyright (c) 1999-2015 Ephox Corp. All rights reserved
|
6
|
+
*
|
7
|
+
* License: http://www.tinymce.com/license
|
8
|
+
* Contributing: http://www.tinymce.com/contributing
|
9
|
+
*/
|
10
|
+
|
11
|
+
/*globals console*/
|
12
|
+
|
13
|
+
/**
|
14
|
+
* This class handles asynchronous/synchronous loading of JavaScript files it will execute callbacks
|
15
|
+
* when various items gets loaded. This class is useful to load external JavaScript files.
|
16
|
+
*
|
17
|
+
* @class tinymce.dom.ScriptLoader
|
18
|
+
* @example
|
19
|
+
* // Load a script from a specific URL using the global script loader
|
20
|
+
* tinymce.ScriptLoader.load('somescript.js');
|
21
|
+
*
|
22
|
+
* // Load a script using a unique instance of the script loader
|
23
|
+
* var scriptLoader = new tinymce.dom.ScriptLoader();
|
24
|
+
*
|
25
|
+
* scriptLoader.load('somescript.js');
|
26
|
+
*
|
27
|
+
* // Load multiple scripts
|
28
|
+
* var scriptLoader = new tinymce.dom.ScriptLoader();
|
29
|
+
*
|
30
|
+
* scriptLoader.add('somescript1.js');
|
31
|
+
* scriptLoader.add('somescript2.js');
|
32
|
+
* scriptLoader.add('somescript3.js');
|
33
|
+
*
|
34
|
+
* scriptLoader.loadQueue(function() {
|
35
|
+
* alert('All scripts are now loaded.');
|
36
|
+
* });
|
37
|
+
*/
|
38
|
+
define("tinymce/dom/ScriptLoader", [
|
39
|
+
"tinymce/dom/DOMUtils",
|
40
|
+
"tinymce/util/Tools"
|
41
|
+
], function(DOMUtils, Tools) {
|
42
|
+
var DOM = DOMUtils.DOM;
|
43
|
+
var each = Tools.each, grep = Tools.grep;
|
44
|
+
|
45
|
+
function ScriptLoader() {
|
46
|
+
var QUEUED = 0,
|
47
|
+
LOADING = 1,
|
48
|
+
LOADED = 2,
|
49
|
+
states = {},
|
50
|
+
queue = [],
|
51
|
+
scriptLoadedCallbacks = {},
|
52
|
+
queueLoadedCallbacks = [],
|
53
|
+
loading = 0,
|
54
|
+
undef;
|
55
|
+
|
56
|
+
/**
|
57
|
+
* Loads a specific script directly without adding it to the load queue.
|
58
|
+
*
|
59
|
+
* @method load
|
60
|
+
* @param {String} url Absolute URL to script to add.
|
61
|
+
* @param {function} callback Optional callback function to execute ones this script gets loaded.
|
62
|
+
*/
|
63
|
+
function loadScript(url, callback) {
|
64
|
+
var dom = DOM, elm, id;
|
65
|
+
|
66
|
+
// Execute callback when script is loaded
|
67
|
+
function done() {
|
68
|
+
dom.remove(id);
|
69
|
+
|
70
|
+
if (elm) {
|
71
|
+
elm.onreadystatechange = elm.onload = elm = null;
|
72
|
+
}
|
73
|
+
|
74
|
+
callback();
|
75
|
+
}
|
76
|
+
|
77
|
+
function error() {
|
78
|
+
/*eslint no-console:0 */
|
79
|
+
|
80
|
+
// Report the error so it's easier for people to spot loading errors
|
81
|
+
if (typeof console !== "undefined" && console.log) {
|
82
|
+
console.log("Failed to load: " + url);
|
83
|
+
}
|
84
|
+
|
85
|
+
// We can't mark it as done if there is a load error since
|
86
|
+
// A) We don't want to produce 404 errors on the server and
|
87
|
+
// B) the onerror event won't fire on all browsers.
|
88
|
+
// done();
|
89
|
+
}
|
90
|
+
|
91
|
+
id = dom.uniqueId();
|
92
|
+
|
93
|
+
// Create new script element
|
94
|
+
elm = document.createElement('script');
|
95
|
+
elm.id = id;
|
96
|
+
elm.type = 'text/javascript';
|
97
|
+
elm.src = Tools._addCacheSuffix(url);
|
98
|
+
|
99
|
+
// Seems that onreadystatechange works better on IE 10 onload seems to fire incorrectly
|
100
|
+
if ("onreadystatechange" in elm) {
|
101
|
+
elm.onreadystatechange = function() {
|
102
|
+
if (/loaded|complete/.test(elm.readyState)) {
|
103
|
+
done();
|
104
|
+
}
|
105
|
+
};
|
106
|
+
} else {
|
107
|
+
elm.onload = done;
|
108
|
+
}
|
109
|
+
|
110
|
+
// Add onerror event will get fired on some browsers but not all of them
|
111
|
+
elm.onerror = error;
|
112
|
+
|
113
|
+
// Add script to document
|
114
|
+
(document.getElementsByTagName('head')[0] || document.body).appendChild(elm);
|
115
|
+
}
|
116
|
+
|
117
|
+
/**
|
118
|
+
* Returns true/false if a script has been loaded or not.
|
119
|
+
*
|
120
|
+
* @method isDone
|
121
|
+
* @param {String} url URL to check for.
|
122
|
+
* @return {Boolean} true/false if the URL is loaded.
|
123
|
+
*/
|
124
|
+
this.isDone = function(url) {
|
125
|
+
return states[url] == LOADED;
|
126
|
+
};
|
127
|
+
|
128
|
+
/**
|
129
|
+
* Marks a specific script to be loaded. This can be useful if a script got loaded outside
|
130
|
+
* the script loader or to skip it from loading some script.
|
131
|
+
*
|
132
|
+
* @method markDone
|
133
|
+
* @param {string} url Absolute URL to the script to mark as loaded.
|
134
|
+
*/
|
135
|
+
this.markDone = function(url) {
|
136
|
+
states[url] = LOADED;
|
137
|
+
};
|
138
|
+
|
139
|
+
/**
|
140
|
+
* Adds a specific script to the load queue of the script loader.
|
141
|
+
*
|
142
|
+
* @method add
|
143
|
+
* @param {String} url Absolute URL to script to add.
|
144
|
+
* @param {function} callback Optional callback function to execute ones this script gets loaded.
|
145
|
+
* @param {Object} scope Optional scope to execute callback in.
|
146
|
+
*/
|
147
|
+
this.add = this.load = function(url, callback, scope) {
|
148
|
+
var state = states[url];
|
149
|
+
|
150
|
+
// Add url to load queue
|
151
|
+
if (state == undef) {
|
152
|
+
queue.push(url);
|
153
|
+
states[url] = QUEUED;
|
154
|
+
}
|
155
|
+
|
156
|
+
if (callback) {
|
157
|
+
// Store away callback for later execution
|
158
|
+
if (!scriptLoadedCallbacks[url]) {
|
159
|
+
scriptLoadedCallbacks[url] = [];
|
160
|
+
}
|
161
|
+
|
162
|
+
scriptLoadedCallbacks[url].push({
|
163
|
+
func: callback,
|
164
|
+
scope: scope || this
|
165
|
+
});
|
166
|
+
}
|
167
|
+
};
|
168
|
+
|
169
|
+
/**
|
170
|
+
* Starts the loading of the queue.
|
171
|
+
*
|
172
|
+
* @method loadQueue
|
173
|
+
* @param {function} callback Optional callback to execute when all queued items are loaded.
|
174
|
+
* @param {Object} scope Optional scope to execute the callback in.
|
175
|
+
*/
|
176
|
+
this.loadQueue = function(callback, scope) {
|
177
|
+
this.loadScripts(queue, callback, scope);
|
178
|
+
};
|
179
|
+
|
180
|
+
/**
|
181
|
+
* Loads the specified queue of files and executes the callback ones they are loaded.
|
182
|
+
* This method is generally not used outside this class but it might be useful in some scenarios.
|
183
|
+
*
|
184
|
+
* @method loadScripts
|
185
|
+
* @param {Array} scripts Array of queue items to load.
|
186
|
+
* @param {function} callback Optional callback to execute ones all items are loaded.
|
187
|
+
* @param {Object} scope Optional scope to execute callback in.
|
188
|
+
*/
|
189
|
+
this.loadScripts = function(scripts, callback, scope) {
|
190
|
+
var loadScripts;
|
191
|
+
|
192
|
+
function execScriptLoadedCallbacks(url) {
|
193
|
+
// Execute URL callback functions
|
194
|
+
each(scriptLoadedCallbacks[url], function(callback) {
|
195
|
+
callback.func.call(callback.scope);
|
196
|
+
});
|
197
|
+
|
198
|
+
scriptLoadedCallbacks[url] = undef;
|
199
|
+
}
|
200
|
+
|
201
|
+
queueLoadedCallbacks.push({
|
202
|
+
func: callback,
|
203
|
+
scope: scope || this
|
204
|
+
});
|
205
|
+
|
206
|
+
loadScripts = function() {
|
207
|
+
var loadingScripts = grep(scripts);
|
208
|
+
|
209
|
+
// Current scripts has been handled
|
210
|
+
scripts.length = 0;
|
211
|
+
|
212
|
+
// Load scripts that needs to be loaded
|
213
|
+
each(loadingScripts, function(url) {
|
214
|
+
// Script is already loaded then execute script callbacks directly
|
215
|
+
if (states[url] == LOADED) {
|
216
|
+
execScriptLoadedCallbacks(url);
|
217
|
+
return;
|
218
|
+
}
|
219
|
+
|
220
|
+
// Is script not loading then start loading it
|
221
|
+
if (states[url] != LOADING) {
|
222
|
+
states[url] = LOADING;
|
223
|
+
loading++;
|
224
|
+
|
225
|
+
loadScript(url, function() {
|
226
|
+
states[url] = LOADED;
|
227
|
+
loading--;
|
228
|
+
|
229
|
+
execScriptLoadedCallbacks(url);
|
230
|
+
|
231
|
+
// Load more scripts if they where added by the recently loaded script
|
232
|
+
loadScripts();
|
233
|
+
});
|
234
|
+
}
|
235
|
+
});
|
236
|
+
|
237
|
+
// No scripts are currently loading then execute all pending queue loaded callbacks
|
238
|
+
if (!loading) {
|
239
|
+
each(queueLoadedCallbacks, function(callback) {
|
240
|
+
callback.func.call(callback.scope);
|
241
|
+
});
|
242
|
+
|
243
|
+
queueLoadedCallbacks.length = 0;
|
244
|
+
}
|
245
|
+
};
|
246
|
+
|
247
|
+
loadScripts();
|
248
|
+
};
|
249
|
+
}
|
250
|
+
|
251
|
+
ScriptLoader.ScriptLoader = new ScriptLoader();
|
252
|
+
|
253
|
+
return ScriptLoader;
|
254
|
+
});
|
@@ -0,0 +1,1008 @@
|
|
1
|
+
/**
|
2
|
+
* Selection.js
|
3
|
+
*
|
4
|
+
* Released under LGPL License.
|
5
|
+
* Copyright (c) 1999-2015 Ephox Corp. All rights reserved
|
6
|
+
*
|
7
|
+
* License: http://www.tinymce.com/license
|
8
|
+
* Contributing: http://www.tinymce.com/contributing
|
9
|
+
*/
|
10
|
+
|
11
|
+
/**
|
12
|
+
* This class handles text and control selection it's an crossbrowser utility class.
|
13
|
+
* Consult the TinyMCE Wiki API for more details and examples on how to use this class.
|
14
|
+
*
|
15
|
+
* @class tinymce.dom.Selection
|
16
|
+
* @example
|
17
|
+
* // Getting the currently selected node for the active editor
|
18
|
+
* alert(tinymce.activeEditor.selection.getNode().nodeName);
|
19
|
+
*/
|
20
|
+
define("tinymce/dom/Selection", [
|
21
|
+
"tinymce/dom/TreeWalker",
|
22
|
+
"tinymce/dom/TridentSelection",
|
23
|
+
"tinymce/dom/ControlSelection",
|
24
|
+
"tinymce/dom/RangeUtils",
|
25
|
+
"tinymce/dom/BookmarkManager",
|
26
|
+
"tinymce/dom/NodeType",
|
27
|
+
"tinymce/Env",
|
28
|
+
"tinymce/util/Tools"
|
29
|
+
], function(TreeWalker, TridentSelection, ControlSelection, RangeUtils, BookmarkManager, NodeType, Env, Tools) {
|
30
|
+
var each = Tools.each, trim = Tools.trim;
|
31
|
+
var isIE = Env.ie;
|
32
|
+
|
33
|
+
/**
|
34
|
+
* Constructs a new selection instance.
|
35
|
+
*
|
36
|
+
* @constructor
|
37
|
+
* @method Selection
|
38
|
+
* @param {tinymce.dom.DOMUtils} dom DOMUtils object reference.
|
39
|
+
* @param {Window} win Window to bind the selection object to.
|
40
|
+
* @param {tinymce.Editor} editor Editor instance of the selection.
|
41
|
+
* @param {tinymce.dom.Serializer} serializer DOM serialization class to use for getContent.
|
42
|
+
*/
|
43
|
+
function Selection(dom, win, serializer, editor) {
|
44
|
+
var self = this;
|
45
|
+
|
46
|
+
self.dom = dom;
|
47
|
+
self.win = win;
|
48
|
+
self.serializer = serializer;
|
49
|
+
self.editor = editor;
|
50
|
+
self.bookmarkManager = new BookmarkManager(self);
|
51
|
+
self.controlSelection = new ControlSelection(self, editor);
|
52
|
+
|
53
|
+
// No W3C Range support
|
54
|
+
if (!self.win.getSelection) {
|
55
|
+
self.tridentSel = new TridentSelection(self);
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
Selection.prototype = {
|
60
|
+
/**
|
61
|
+
* Move the selection cursor range to the specified node and offset.
|
62
|
+
* If there is no node specified it will move it to the first suitable location within the body.
|
63
|
+
*
|
64
|
+
* @method setCursorLocation
|
65
|
+
* @param {Node} node Optional node to put the cursor in.
|
66
|
+
* @param {Number} offset Optional offset from the start of the node to put the cursor at.
|
67
|
+
*/
|
68
|
+
setCursorLocation: function(node, offset) {
|
69
|
+
var self = this, rng = self.dom.createRng();
|
70
|
+
|
71
|
+
if (!node) {
|
72
|
+
self._moveEndPoint(rng, self.editor.getBody(), true);
|
73
|
+
self.setRng(rng);
|
74
|
+
} else {
|
75
|
+
rng.setStart(node, offset);
|
76
|
+
rng.setEnd(node, offset);
|
77
|
+
self.setRng(rng);
|
78
|
+
self.collapse(false);
|
79
|
+
}
|
80
|
+
},
|
81
|
+
|
82
|
+
/**
|
83
|
+
* Returns the selected contents using the DOM serializer passed in to this class.
|
84
|
+
*
|
85
|
+
* @method getContent
|
86
|
+
* @param {Object} args Optional settings class with for example output format text or html.
|
87
|
+
* @return {String} Selected contents in for example HTML format.
|
88
|
+
* @example
|
89
|
+
* // Alerts the currently selected contents
|
90
|
+
* alert(tinymce.activeEditor.selection.getContent());
|
91
|
+
*
|
92
|
+
* // Alerts the currently selected contents as plain text
|
93
|
+
* alert(tinymce.activeEditor.selection.getContent({format: 'text'}));
|
94
|
+
*/
|
95
|
+
getContent: function(args) {
|
96
|
+
var self = this, rng = self.getRng(), tmpElm = self.dom.create("body");
|
97
|
+
var se = self.getSel(), whiteSpaceBefore, whiteSpaceAfter, fragment;
|
98
|
+
|
99
|
+
args = args || {};
|
100
|
+
whiteSpaceBefore = whiteSpaceAfter = '';
|
101
|
+
args.get = true;
|
102
|
+
args.format = args.format || 'html';
|
103
|
+
args.selection = true;
|
104
|
+
self.editor.fire('BeforeGetContent', args);
|
105
|
+
|
106
|
+
if (args.format == 'text') {
|
107
|
+
return self.isCollapsed() ? '' : (rng.text || (se.toString ? se.toString() : ''));
|
108
|
+
}
|
109
|
+
|
110
|
+
if (rng.cloneContents) {
|
111
|
+
fragment = rng.cloneContents();
|
112
|
+
|
113
|
+
if (fragment) {
|
114
|
+
tmpElm.appendChild(fragment);
|
115
|
+
}
|
116
|
+
} else if (rng.item !== undefined || rng.htmlText !== undefined) {
|
117
|
+
// IE will produce invalid markup if elements are present that
|
118
|
+
// it doesn't understand like custom elements or HTML5 elements.
|
119
|
+
// Adding a BR in front of the contents and then remoiving it seems to fix it though.
|
120
|
+
tmpElm.innerHTML = '<br>' + (rng.item ? rng.item(0).outerHTML : rng.htmlText);
|
121
|
+
tmpElm.removeChild(tmpElm.firstChild);
|
122
|
+
} else {
|
123
|
+
tmpElm.innerHTML = rng.toString();
|
124
|
+
}
|
125
|
+
|
126
|
+
// Keep whitespace before and after
|
127
|
+
if (/^\s/.test(tmpElm.innerHTML)) {
|
128
|
+
whiteSpaceBefore = ' ';
|
129
|
+
}
|
130
|
+
|
131
|
+
if (/\s+$/.test(tmpElm.innerHTML)) {
|
132
|
+
whiteSpaceAfter = ' ';
|
133
|
+
}
|
134
|
+
|
135
|
+
args.getInner = true;
|
136
|
+
|
137
|
+
args.content = self.isCollapsed() ? '' : whiteSpaceBefore + self.serializer.serialize(tmpElm, args) + whiteSpaceAfter;
|
138
|
+
self.editor.fire('GetContent', args);
|
139
|
+
|
140
|
+
return args.content;
|
141
|
+
},
|
142
|
+
|
143
|
+
/**
|
144
|
+
* Sets the current selection to the specified content. If any contents is selected it will be replaced
|
145
|
+
* with the contents passed in to this function. If there is no selection the contents will be inserted
|
146
|
+
* where the caret is placed in the editor/page.
|
147
|
+
*
|
148
|
+
* @method setContent
|
149
|
+
* @param {String} content HTML contents to set could also be other formats depending on settings.
|
150
|
+
* @param {Object} args Optional settings object with for example data format.
|
151
|
+
* @example
|
152
|
+
* // Inserts some HTML contents at the current selection
|
153
|
+
* tinymce.activeEditor.selection.setContent('<strong>Some contents</strong>');
|
154
|
+
*/
|
155
|
+
setContent: function(content, args) {
|
156
|
+
var self = this, rng = self.getRng(), caretNode, doc = self.win.document, frag, temp;
|
157
|
+
|
158
|
+
args = args || {format: 'html'};
|
159
|
+
args.set = true;
|
160
|
+
args.selection = true;
|
161
|
+
args.content = content;
|
162
|
+
|
163
|
+
// Dispatch before set content event
|
164
|
+
if (!args.no_events) {
|
165
|
+
self.editor.fire('BeforeSetContent', args);
|
166
|
+
}
|
167
|
+
|
168
|
+
content = args.content;
|
169
|
+
|
170
|
+
if (rng.insertNode) {
|
171
|
+
// Make caret marker since insertNode places the caret in the beginning of text after insert
|
172
|
+
content += '<span id="__caret">_</span>';
|
173
|
+
|
174
|
+
// Delete and insert new node
|
175
|
+
if (rng.startContainer == doc && rng.endContainer == doc) {
|
176
|
+
// WebKit will fail if the body is empty since the range is then invalid and it can't insert contents
|
177
|
+
doc.body.innerHTML = content;
|
178
|
+
} else {
|
179
|
+
rng.deleteContents();
|
180
|
+
|
181
|
+
if (doc.body.childNodes.length === 0) {
|
182
|
+
doc.body.innerHTML = content;
|
183
|
+
} else {
|
184
|
+
// createContextualFragment doesn't exists in IE 9 DOMRanges
|
185
|
+
if (rng.createContextualFragment) {
|
186
|
+
rng.insertNode(rng.createContextualFragment(content));
|
187
|
+
} else {
|
188
|
+
// Fake createContextualFragment call in IE 9
|
189
|
+
frag = doc.createDocumentFragment();
|
190
|
+
temp = doc.createElement('div');
|
191
|
+
|
192
|
+
frag.appendChild(temp);
|
193
|
+
temp.outerHTML = content;
|
194
|
+
|
195
|
+
rng.insertNode(frag);
|
196
|
+
}
|
197
|
+
}
|
198
|
+
}
|
199
|
+
|
200
|
+
// Move to caret marker
|
201
|
+
caretNode = self.dom.get('__caret');
|
202
|
+
|
203
|
+
// Make sure we wrap it compleatly, Opera fails with a simple select call
|
204
|
+
rng = doc.createRange();
|
205
|
+
rng.setStartBefore(caretNode);
|
206
|
+
rng.setEndBefore(caretNode);
|
207
|
+
self.setRng(rng);
|
208
|
+
|
209
|
+
// Remove the caret position
|
210
|
+
self.dom.remove('__caret');
|
211
|
+
|
212
|
+
try {
|
213
|
+
self.setRng(rng);
|
214
|
+
} catch (ex) {
|
215
|
+
// Might fail on Opera for some odd reason
|
216
|
+
}
|
217
|
+
} else {
|
218
|
+
if (rng.item) {
|
219
|
+
// Delete content and get caret text selection
|
220
|
+
doc.execCommand('Delete', false, null);
|
221
|
+
rng = self.getRng();
|
222
|
+
}
|
223
|
+
|
224
|
+
// Explorer removes spaces from the beginning of pasted contents
|
225
|
+
if (/^\s+/.test(content)) {
|
226
|
+
rng.pasteHTML('<span id="__mce_tmp">_</span>' + content);
|
227
|
+
self.dom.remove('__mce_tmp');
|
228
|
+
} else {
|
229
|
+
rng.pasteHTML(content);
|
230
|
+
}
|
231
|
+
}
|
232
|
+
|
233
|
+
// Dispatch set content event
|
234
|
+
if (!args.no_events) {
|
235
|
+
self.editor.fire('SetContent', args);
|
236
|
+
}
|
237
|
+
},
|
238
|
+
|
239
|
+
/**
|
240
|
+
* Returns the start element of a selection range. If the start is in a text
|
241
|
+
* node the parent element will be returned.
|
242
|
+
*
|
243
|
+
* @method getStart
|
244
|
+
* @param {Boolean} real Optional state to get the real parent when the selection is collapsed not the closest element.
|
245
|
+
* @return {Element} Start element of selection range.
|
246
|
+
*/
|
247
|
+
getStart: function(real) {
|
248
|
+
var self = this, rng = self.getRng(), startElement, parentElement, checkRng, node;
|
249
|
+
|
250
|
+
if (rng.duplicate || rng.item) {
|
251
|
+
// Control selection, return first item
|
252
|
+
if (rng.item) {
|
253
|
+
return rng.item(0);
|
254
|
+
}
|
255
|
+
|
256
|
+
// Get start element
|
257
|
+
checkRng = rng.duplicate();
|
258
|
+
checkRng.collapse(1);
|
259
|
+
startElement = checkRng.parentElement();
|
260
|
+
if (startElement.ownerDocument !== self.dom.doc) {
|
261
|
+
startElement = self.dom.getRoot();
|
262
|
+
}
|
263
|
+
|
264
|
+
// Check if range parent is inside the start element, then return the inner parent element
|
265
|
+
// This will fix issues when a single element is selected, IE would otherwise return the wrong start element
|
266
|
+
parentElement = node = rng.parentElement();
|
267
|
+
while ((node = node.parentNode)) {
|
268
|
+
if (node == startElement) {
|
269
|
+
startElement = parentElement;
|
270
|
+
break;
|
271
|
+
}
|
272
|
+
}
|
273
|
+
|
274
|
+
return startElement;
|
275
|
+
}
|
276
|
+
|
277
|
+
startElement = rng.startContainer;
|
278
|
+
|
279
|
+
if (startElement.nodeType == 1 && startElement.hasChildNodes()) {
|
280
|
+
if (!real || !rng.collapsed) {
|
281
|
+
startElement = startElement.childNodes[Math.min(startElement.childNodes.length - 1, rng.startOffset)];
|
282
|
+
}
|
283
|
+
}
|
284
|
+
|
285
|
+
if (startElement && startElement.nodeType == 3) {
|
286
|
+
return startElement.parentNode;
|
287
|
+
}
|
288
|
+
|
289
|
+
return startElement;
|
290
|
+
},
|
291
|
+
|
292
|
+
/**
|
293
|
+
* Returns the end element of a selection range. If the end is in a text
|
294
|
+
* node the parent element will be returned.
|
295
|
+
*
|
296
|
+
* @method getEnd
|
297
|
+
* @param {Boolean} real Optional state to get the real parent when the selection is collapsed not the closest element.
|
298
|
+
* @return {Element} End element of selection range.
|
299
|
+
*/
|
300
|
+
getEnd: function(real) {
|
301
|
+
var self = this, rng = self.getRng(), endElement, endOffset;
|
302
|
+
|
303
|
+
if (rng.duplicate || rng.item) {
|
304
|
+
if (rng.item) {
|
305
|
+
return rng.item(0);
|
306
|
+
}
|
307
|
+
|
308
|
+
rng = rng.duplicate();
|
309
|
+
rng.collapse(0);
|
310
|
+
endElement = rng.parentElement();
|
311
|
+
if (endElement.ownerDocument !== self.dom.doc) {
|
312
|
+
endElement = self.dom.getRoot();
|
313
|
+
}
|
314
|
+
|
315
|
+
if (endElement && endElement.nodeName == 'BODY') {
|
316
|
+
return endElement.lastChild || endElement;
|
317
|
+
}
|
318
|
+
|
319
|
+
return endElement;
|
320
|
+
}
|
321
|
+
|
322
|
+
endElement = rng.endContainer;
|
323
|
+
endOffset = rng.endOffset;
|
324
|
+
|
325
|
+
if (endElement.nodeType == 1 && endElement.hasChildNodes()) {
|
326
|
+
if (!real || !rng.collapsed) {
|
327
|
+
endElement = endElement.childNodes[endOffset > 0 ? endOffset - 1 : endOffset];
|
328
|
+
}
|
329
|
+
}
|
330
|
+
|
331
|
+
if (endElement && endElement.nodeType == 3) {
|
332
|
+
return endElement.parentNode;
|
333
|
+
}
|
334
|
+
|
335
|
+
return endElement;
|
336
|
+
},
|
337
|
+
|
338
|
+
/**
|
339
|
+
* Returns a bookmark location for the current selection. This bookmark object
|
340
|
+
* can then be used to restore the selection after some content modification to the document.
|
341
|
+
*
|
342
|
+
* @method getBookmark
|
343
|
+
* @param {Number} type Optional state if the bookmark should be simple or not. Default is complex.
|
344
|
+
* @param {Boolean} normalized Optional state that enables you to get a position that it would be after normalization.
|
345
|
+
* @return {Object} Bookmark object, use moveToBookmark with this object to restore the selection.
|
346
|
+
* @example
|
347
|
+
* // Stores a bookmark of the current selection
|
348
|
+
* var bm = tinymce.activeEditor.selection.getBookmark();
|
349
|
+
*
|
350
|
+
* tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
|
351
|
+
*
|
352
|
+
* // Restore the selection bookmark
|
353
|
+
* tinymce.activeEditor.selection.moveToBookmark(bm);
|
354
|
+
*/
|
355
|
+
getBookmark: function(type, normalized) {
|
356
|
+
return this.bookmarkManager.getBookmark(type, normalized);
|
357
|
+
},
|
358
|
+
|
359
|
+
/**
|
360
|
+
* Restores the selection to the specified bookmark.
|
361
|
+
*
|
362
|
+
* @method moveToBookmark
|
363
|
+
* @param {Object} bookmark Bookmark to restore selection from.
|
364
|
+
* @return {Boolean} true/false if it was successful or not.
|
365
|
+
* @example
|
366
|
+
* // Stores a bookmark of the current selection
|
367
|
+
* var bm = tinymce.activeEditor.selection.getBookmark();
|
368
|
+
*
|
369
|
+
* tinymce.activeEditor.setContent(tinymce.activeEditor.getContent() + 'Some new content');
|
370
|
+
*
|
371
|
+
* // Restore the selection bookmark
|
372
|
+
* tinymce.activeEditor.selection.moveToBookmark(bm);
|
373
|
+
*/
|
374
|
+
moveToBookmark: function(bookmark) {
|
375
|
+
return this.bookmarkManager.moveToBookmark(bookmark);
|
376
|
+
},
|
377
|
+
|
378
|
+
/**
|
379
|
+
* Selects the specified element. This will place the start and end of the selection range around the element.
|
380
|
+
*
|
381
|
+
* @method select
|
382
|
+
* @param {Element} node HTML DOM element to select.
|
383
|
+
* @param {Boolean} content Optional bool state if the contents should be selected or not on non IE browser.
|
384
|
+
* @return {Element} Selected element the same element as the one that got passed in.
|
385
|
+
* @example
|
386
|
+
* // Select the first paragraph in the active editor
|
387
|
+
* tinymce.activeEditor.selection.select(tinymce.activeEditor.dom.select('p')[0]);
|
388
|
+
*/
|
389
|
+
select: function(node, content) {
|
390
|
+
var self = this, dom = self.dom, rng = dom.createRng(), idx;
|
391
|
+
|
392
|
+
// Clear stored range set by FocusManager
|
393
|
+
self.lastFocusBookmark = null;
|
394
|
+
|
395
|
+
if (node) {
|
396
|
+
if (!content && self.controlSelection.controlSelect(node)) {
|
397
|
+
return;
|
398
|
+
}
|
399
|
+
|
400
|
+
idx = dom.nodeIndex(node);
|
401
|
+
rng.setStart(node.parentNode, idx);
|
402
|
+
rng.setEnd(node.parentNode, idx + 1);
|
403
|
+
|
404
|
+
// Find first/last text node or BR element
|
405
|
+
if (content) {
|
406
|
+
self._moveEndPoint(rng, node, true);
|
407
|
+
self._moveEndPoint(rng, node);
|
408
|
+
}
|
409
|
+
|
410
|
+
self.setRng(rng);
|
411
|
+
}
|
412
|
+
|
413
|
+
return node;
|
414
|
+
},
|
415
|
+
|
416
|
+
/**
|
417
|
+
* Returns true/false if the selection range is collapsed or not. Collapsed means if it's a caret or a larger selection.
|
418
|
+
*
|
419
|
+
* @method isCollapsed
|
420
|
+
* @return {Boolean} true/false state if the selection range is collapsed or not.
|
421
|
+
* Collapsed means if it's a caret or a larger selection.
|
422
|
+
*/
|
423
|
+
isCollapsed: function() {
|
424
|
+
var self = this, rng = self.getRng(), sel = self.getSel();
|
425
|
+
|
426
|
+
if (!rng || rng.item) {
|
427
|
+
return false;
|
428
|
+
}
|
429
|
+
|
430
|
+
if (rng.compareEndPoints) {
|
431
|
+
return rng.compareEndPoints('StartToEnd', rng) === 0;
|
432
|
+
}
|
433
|
+
|
434
|
+
return !sel || rng.collapsed;
|
435
|
+
},
|
436
|
+
|
437
|
+
/**
|
438
|
+
* Collapse the selection to start or end of range.
|
439
|
+
*
|
440
|
+
* @method collapse
|
441
|
+
* @param {Boolean} toStart Optional boolean state if to collapse to end or not. Defaults to false.
|
442
|
+
*/
|
443
|
+
collapse: function(toStart) {
|
444
|
+
var self = this, rng = self.getRng(), node;
|
445
|
+
|
446
|
+
// Control range on IE
|
447
|
+
if (rng.item) {
|
448
|
+
node = rng.item(0);
|
449
|
+
rng = self.win.document.body.createTextRange();
|
450
|
+
rng.moveToElementText(node);
|
451
|
+
}
|
452
|
+
|
453
|
+
rng.collapse(!!toStart);
|
454
|
+
self.setRng(rng);
|
455
|
+
},
|
456
|
+
|
457
|
+
/**
|
458
|
+
* Returns the browsers internal selection object.
|
459
|
+
*
|
460
|
+
* @method getSel
|
461
|
+
* @return {Selection} Internal browser selection object.
|
462
|
+
*/
|
463
|
+
getSel: function() {
|
464
|
+
var win = this.win;
|
465
|
+
|
466
|
+
return win.getSelection ? win.getSelection() : win.document.selection;
|
467
|
+
},
|
468
|
+
|
469
|
+
/**
|
470
|
+
* Returns the browsers internal range object.
|
471
|
+
*
|
472
|
+
* @method getRng
|
473
|
+
* @param {Boolean} w3c Forces a compatible W3C range on IE.
|
474
|
+
* @return {Range} Internal browser range object.
|
475
|
+
* @see http://www.quirksmode.org/dom/range_intro.html
|
476
|
+
* @see http://www.dotvoid.com/2001/03/using-the-range-object-in-mozilla/
|
477
|
+
*/
|
478
|
+
getRng: function(w3c) {
|
479
|
+
var self = this, selection, rng, elm, doc, ieRng, evt;
|
480
|
+
|
481
|
+
function tryCompareBoundaryPoints(how, sourceRange, destinationRange) {
|
482
|
+
try {
|
483
|
+
return sourceRange.compareBoundaryPoints(how, destinationRange);
|
484
|
+
} catch (ex) {
|
485
|
+
// Gecko throws wrong document exception if the range points
|
486
|
+
// to nodes that where removed from the dom #6690
|
487
|
+
// Browsers should mutate existing DOMRange instances so that they always point
|
488
|
+
// to something in the document this is not the case in Gecko works fine in IE/WebKit/Blink
|
489
|
+
// For performance reasons just return -1
|
490
|
+
return -1;
|
491
|
+
}
|
492
|
+
}
|
493
|
+
|
494
|
+
if (!self.win) {
|
495
|
+
return null;
|
496
|
+
}
|
497
|
+
|
498
|
+
doc = self.win.document;
|
499
|
+
|
500
|
+
// Use last rng passed from FocusManager if it's available this enables
|
501
|
+
// calls to editor.selection.getStart() to work when caret focus is lost on IE
|
502
|
+
if (!w3c && self.lastFocusBookmark) {
|
503
|
+
var bookmark = self.lastFocusBookmark;
|
504
|
+
|
505
|
+
// Convert bookmark to range IE 11 fix
|
506
|
+
if (bookmark.startContainer) {
|
507
|
+
rng = doc.createRange();
|
508
|
+
rng.setStart(bookmark.startContainer, bookmark.startOffset);
|
509
|
+
rng.setEnd(bookmark.endContainer, bookmark.endOffset);
|
510
|
+
} else {
|
511
|
+
rng = bookmark;
|
512
|
+
}
|
513
|
+
|
514
|
+
return rng;
|
515
|
+
}
|
516
|
+
|
517
|
+
// Found tridentSel object then we need to use that one
|
518
|
+
if (w3c && self.tridentSel) {
|
519
|
+
return self.tridentSel.getRangeAt(0);
|
520
|
+
}
|
521
|
+
|
522
|
+
try {
|
523
|
+
if ((selection = self.getSel())) {
|
524
|
+
if (selection.rangeCount > 0) {
|
525
|
+
rng = selection.getRangeAt(0);
|
526
|
+
} else {
|
527
|
+
rng = selection.createRange ? selection.createRange() : doc.createRange();
|
528
|
+
}
|
529
|
+
}
|
530
|
+
} catch (ex) {
|
531
|
+
// IE throws unspecified error here if TinyMCE is placed in a frame/iframe
|
532
|
+
}
|
533
|
+
|
534
|
+
evt = self.editor.fire('GetSelectionRange', {range: rng});
|
535
|
+
if (evt.range !== rng) {
|
536
|
+
return evt.range;
|
537
|
+
}
|
538
|
+
|
539
|
+
// We have W3C ranges and it's IE then fake control selection since IE9 doesn't handle that correctly yet
|
540
|
+
// IE 11 doesn't support the selection object so we check for that as well
|
541
|
+
if (isIE && rng && rng.setStart && doc.selection) {
|
542
|
+
try {
|
543
|
+
// IE will sometimes throw an exception here
|
544
|
+
ieRng = doc.selection.createRange();
|
545
|
+
} catch (ex) {
|
546
|
+
// Ignore
|
547
|
+
}
|
548
|
+
|
549
|
+
if (ieRng && ieRng.item) {
|
550
|
+
elm = ieRng.item(0);
|
551
|
+
rng = doc.createRange();
|
552
|
+
rng.setStartBefore(elm);
|
553
|
+
rng.setEndAfter(elm);
|
554
|
+
}
|
555
|
+
}
|
556
|
+
|
557
|
+
// No range found then create an empty one
|
558
|
+
// This can occur when the editor is placed in a hidden container element on Gecko
|
559
|
+
// Or on IE when there was an exception
|
560
|
+
if (!rng) {
|
561
|
+
rng = doc.createRange ? doc.createRange() : doc.body.createTextRange();
|
562
|
+
}
|
563
|
+
|
564
|
+
// If range is at start of document then move it to start of body
|
565
|
+
if (rng.setStart && rng.startContainer.nodeType === 9 && rng.collapsed) {
|
566
|
+
elm = self.dom.getRoot();
|
567
|
+
rng.setStart(elm, 0);
|
568
|
+
rng.setEnd(elm, 0);
|
569
|
+
}
|
570
|
+
|
571
|
+
if (self.selectedRange && self.explicitRange) {
|
572
|
+
if (tryCompareBoundaryPoints(rng.START_TO_START, rng, self.selectedRange) === 0 &&
|
573
|
+
tryCompareBoundaryPoints(rng.END_TO_END, rng, self.selectedRange) === 0) {
|
574
|
+
// Safari, Opera and Chrome only ever select text which causes the range to change.
|
575
|
+
// This lets us use the originally set range if the selection hasn't been changed by the user.
|
576
|
+
rng = self.explicitRange;
|
577
|
+
} else {
|
578
|
+
self.selectedRange = null;
|
579
|
+
self.explicitRange = null;
|
580
|
+
}
|
581
|
+
}
|
582
|
+
|
583
|
+
return rng;
|
584
|
+
},
|
585
|
+
|
586
|
+
/**
|
587
|
+
* Changes the selection to the specified DOM range.
|
588
|
+
*
|
589
|
+
* @method setRng
|
590
|
+
* @param {Range} rng Range to select.
|
591
|
+
* @param {Boolean} forward Optional boolean if the selection is forwards or backwards.
|
592
|
+
*/
|
593
|
+
setRng: function(rng, forward) {
|
594
|
+
var self = this, sel, node, evt;
|
595
|
+
|
596
|
+
if (!rng) {
|
597
|
+
return;
|
598
|
+
}
|
599
|
+
|
600
|
+
// Is IE specific range
|
601
|
+
if (rng.select) {
|
602
|
+
self.explicitRange = null;
|
603
|
+
|
604
|
+
try {
|
605
|
+
rng.select();
|
606
|
+
} catch (ex) {
|
607
|
+
// Needed for some odd IE bug #1843306
|
608
|
+
}
|
609
|
+
|
610
|
+
return;
|
611
|
+
}
|
612
|
+
|
613
|
+
if (!self.tridentSel) {
|
614
|
+
sel = self.getSel();
|
615
|
+
|
616
|
+
evt = self.editor.fire('SetSelectionRange', {range: rng});
|
617
|
+
rng = evt.range;
|
618
|
+
|
619
|
+
if (sel) {
|
620
|
+
self.explicitRange = rng;
|
621
|
+
|
622
|
+
try {
|
623
|
+
sel.removeAllRanges();
|
624
|
+
sel.addRange(rng);
|
625
|
+
} catch (ex) {
|
626
|
+
// IE might throw errors here if the editor is within a hidden container and selection is changed
|
627
|
+
}
|
628
|
+
|
629
|
+
// Forward is set to false and we have an extend function
|
630
|
+
if (forward === false && sel.extend) {
|
631
|
+
sel.collapse(rng.endContainer, rng.endOffset);
|
632
|
+
sel.extend(rng.startContainer, rng.startOffset);
|
633
|
+
}
|
634
|
+
|
635
|
+
// adding range isn't always successful so we need to check range count otherwise an exception can occur
|
636
|
+
self.selectedRange = sel.rangeCount > 0 ? sel.getRangeAt(0) : null;
|
637
|
+
}
|
638
|
+
|
639
|
+
// WebKit egde case selecting images works better using setBaseAndExtent
|
640
|
+
if (!rng.collapsed && rng.startContainer == rng.endContainer && sel.setBaseAndExtent && !Env.ie) {
|
641
|
+
if (rng.endOffset - rng.startOffset < 2) {
|
642
|
+
if (rng.startContainer.hasChildNodes()) {
|
643
|
+
node = rng.startContainer.childNodes[rng.startOffset];
|
644
|
+
if (node && node.tagName == 'IMG') {
|
645
|
+
self.getSel().setBaseAndExtent(node, 0, node, 1);
|
646
|
+
}
|
647
|
+
}
|
648
|
+
}
|
649
|
+
}
|
650
|
+
} else {
|
651
|
+
// Is W3C Range fake range on IE
|
652
|
+
if (rng.cloneRange) {
|
653
|
+
try {
|
654
|
+
self.tridentSel.addRange(rng);
|
655
|
+
} catch (ex) {
|
656
|
+
//IE9 throws an error here if called before selection is placed in the editor
|
657
|
+
}
|
658
|
+
}
|
659
|
+
}
|
660
|
+
},
|
661
|
+
|
662
|
+
/**
|
663
|
+
* Sets the current selection to the specified DOM element.
|
664
|
+
*
|
665
|
+
* @method setNode
|
666
|
+
* @param {Element} elm Element to set as the contents of the selection.
|
667
|
+
* @return {Element} Returns the element that got passed in.
|
668
|
+
* @example
|
669
|
+
* // Inserts a DOM node at current selection/caret location
|
670
|
+
* tinymce.activeEditor.selection.setNode(tinymce.activeEditor.dom.create('img', {src: 'some.gif', title: 'some title'}));
|
671
|
+
*/
|
672
|
+
setNode: function(elm) {
|
673
|
+
var self = this;
|
674
|
+
|
675
|
+
self.setContent(self.dom.getOuterHTML(elm));
|
676
|
+
|
677
|
+
return elm;
|
678
|
+
},
|
679
|
+
|
680
|
+
/**
|
681
|
+
* Returns the currently selected element or the common ancestor element for both start and end of the selection.
|
682
|
+
*
|
683
|
+
* @method getNode
|
684
|
+
* @return {Element} Currently selected element or common ancestor element.
|
685
|
+
* @example
|
686
|
+
* // Alerts the currently selected elements node name
|
687
|
+
* alert(tinymce.activeEditor.selection.getNode().nodeName);
|
688
|
+
*/
|
689
|
+
getNode: function() {
|
690
|
+
var self = this, rng = self.getRng(), elm;
|
691
|
+
var startContainer = rng.startContainer, endContainer = rng.endContainer;
|
692
|
+
var startOffset = rng.startOffset, endOffset = rng.endOffset, root = self.dom.getRoot();
|
693
|
+
|
694
|
+
function skipEmptyTextNodes(node, forwards) {
|
695
|
+
var orig = node;
|
696
|
+
|
697
|
+
while (node && node.nodeType === 3 && node.length === 0) {
|
698
|
+
node = forwards ? node.nextSibling : node.previousSibling;
|
699
|
+
}
|
700
|
+
|
701
|
+
return node || orig;
|
702
|
+
}
|
703
|
+
|
704
|
+
// Range maybe lost after the editor is made visible again
|
705
|
+
if (!rng) {
|
706
|
+
return root;
|
707
|
+
}
|
708
|
+
|
709
|
+
if (rng.setStart) {
|
710
|
+
elm = rng.commonAncestorContainer;
|
711
|
+
|
712
|
+
// Handle selection a image or other control like element such as anchors
|
713
|
+
if (!rng.collapsed) {
|
714
|
+
if (startContainer == endContainer) {
|
715
|
+
if (endOffset - startOffset < 2) {
|
716
|
+
if (startContainer.hasChildNodes()) {
|
717
|
+
elm = startContainer.childNodes[startOffset];
|
718
|
+
}
|
719
|
+
}
|
720
|
+
}
|
721
|
+
|
722
|
+
// If the anchor node is a element instead of a text node then return this element
|
723
|
+
//if (tinymce.isWebKit && sel.anchorNode && sel.anchorNode.nodeType == 1)
|
724
|
+
// return sel.anchorNode.childNodes[sel.anchorOffset];
|
725
|
+
|
726
|
+
// Handle cases where the selection is immediately wrapped around a node and return that node instead of it's parent.
|
727
|
+
// This happens when you double click an underlined word in FireFox.
|
728
|
+
if (startContainer.nodeType === 3 && endContainer.nodeType === 3) {
|
729
|
+
if (startContainer.length === startOffset) {
|
730
|
+
startContainer = skipEmptyTextNodes(startContainer.nextSibling, true);
|
731
|
+
} else {
|
732
|
+
startContainer = startContainer.parentNode;
|
733
|
+
}
|
734
|
+
|
735
|
+
if (endOffset === 0) {
|
736
|
+
endContainer = skipEmptyTextNodes(endContainer.previousSibling, false);
|
737
|
+
} else {
|
738
|
+
endContainer = endContainer.parentNode;
|
739
|
+
}
|
740
|
+
|
741
|
+
if (startContainer && startContainer === endContainer) {
|
742
|
+
return startContainer;
|
743
|
+
}
|
744
|
+
}
|
745
|
+
}
|
746
|
+
|
747
|
+
if (elm && elm.nodeType == 3) {
|
748
|
+
return elm.parentNode;
|
749
|
+
}
|
750
|
+
|
751
|
+
return elm;
|
752
|
+
}
|
753
|
+
|
754
|
+
elm = rng.item ? rng.item(0) : rng.parentElement();
|
755
|
+
|
756
|
+
// IE 7 might return elements outside the iframe
|
757
|
+
if (elm.ownerDocument !== self.win.document) {
|
758
|
+
elm = root;
|
759
|
+
}
|
760
|
+
|
761
|
+
return elm;
|
762
|
+
},
|
763
|
+
|
764
|
+
getSelectedBlocks: function(startElm, endElm) {
|
765
|
+
var self = this, dom = self.dom, node, root, selectedBlocks = [];
|
766
|
+
|
767
|
+
root = dom.getRoot();
|
768
|
+
startElm = dom.getParent(startElm || self.getStart(), dom.isBlock);
|
769
|
+
endElm = dom.getParent(endElm || self.getEnd(), dom.isBlock);
|
770
|
+
|
771
|
+
if (startElm && startElm != root) {
|
772
|
+
selectedBlocks.push(startElm);
|
773
|
+
}
|
774
|
+
|
775
|
+
if (startElm && endElm && startElm != endElm) {
|
776
|
+
node = startElm;
|
777
|
+
|
778
|
+
var walker = new TreeWalker(startElm, root);
|
779
|
+
while ((node = walker.next()) && node != endElm) {
|
780
|
+
if (dom.isBlock(node)) {
|
781
|
+
selectedBlocks.push(node);
|
782
|
+
}
|
783
|
+
}
|
784
|
+
}
|
785
|
+
|
786
|
+
if (endElm && startElm != endElm && endElm != root) {
|
787
|
+
selectedBlocks.push(endElm);
|
788
|
+
}
|
789
|
+
|
790
|
+
return selectedBlocks;
|
791
|
+
},
|
792
|
+
|
793
|
+
isForward: function() {
|
794
|
+
var dom = this.dom, sel = this.getSel(), anchorRange, focusRange;
|
795
|
+
|
796
|
+
// No support for selection direction then always return true
|
797
|
+
if (!sel || !sel.anchorNode || !sel.focusNode) {
|
798
|
+
return true;
|
799
|
+
}
|
800
|
+
|
801
|
+
anchorRange = dom.createRng();
|
802
|
+
anchorRange.setStart(sel.anchorNode, sel.anchorOffset);
|
803
|
+
anchorRange.collapse(true);
|
804
|
+
|
805
|
+
focusRange = dom.createRng();
|
806
|
+
focusRange.setStart(sel.focusNode, sel.focusOffset);
|
807
|
+
focusRange.collapse(true);
|
808
|
+
|
809
|
+
return anchorRange.compareBoundaryPoints(anchorRange.START_TO_START, focusRange) <= 0;
|
810
|
+
},
|
811
|
+
|
812
|
+
normalize: function() {
|
813
|
+
var self = this, rng = self.getRng();
|
814
|
+
|
815
|
+
if (Env.range && new RangeUtils(self.dom).normalize(rng)) {
|
816
|
+
self.setRng(rng, self.isForward());
|
817
|
+
}
|
818
|
+
|
819
|
+
return rng;
|
820
|
+
},
|
821
|
+
|
822
|
+
/**
|
823
|
+
* Executes callback when the current selection starts/stops matching the specified selector. The current
|
824
|
+
* state will be passed to the callback as it's first argument.
|
825
|
+
*
|
826
|
+
* @method selectorChanged
|
827
|
+
* @param {String} selector CSS selector to check for.
|
828
|
+
* @param {function} callback Callback with state and args when the selector is matches or not.
|
829
|
+
*/
|
830
|
+
selectorChanged: function(selector, callback) {
|
831
|
+
var self = this, currentSelectors;
|
832
|
+
|
833
|
+
if (!self.selectorChangedData) {
|
834
|
+
self.selectorChangedData = {};
|
835
|
+
currentSelectors = {};
|
836
|
+
|
837
|
+
self.editor.on('NodeChange', function(e) {
|
838
|
+
var node = e.element, dom = self.dom, parents = dom.getParents(node, null, dom.getRoot()), matchedSelectors = {};
|
839
|
+
|
840
|
+
// Check for new matching selectors
|
841
|
+
each(self.selectorChangedData, function(callbacks, selector) {
|
842
|
+
each(parents, function(node) {
|
843
|
+
if (dom.is(node, selector)) {
|
844
|
+
if (!currentSelectors[selector]) {
|
845
|
+
// Execute callbacks
|
846
|
+
each(callbacks, function(callback) {
|
847
|
+
callback(true, {node: node, selector: selector, parents: parents});
|
848
|
+
});
|
849
|
+
|
850
|
+
currentSelectors[selector] = callbacks;
|
851
|
+
}
|
852
|
+
|
853
|
+
matchedSelectors[selector] = callbacks;
|
854
|
+
return false;
|
855
|
+
}
|
856
|
+
});
|
857
|
+
});
|
858
|
+
|
859
|
+
// Check if current selectors still match
|
860
|
+
each(currentSelectors, function(callbacks, selector) {
|
861
|
+
if (!matchedSelectors[selector]) {
|
862
|
+
delete currentSelectors[selector];
|
863
|
+
|
864
|
+
each(callbacks, function(callback) {
|
865
|
+
callback(false, {node: node, selector: selector, parents: parents});
|
866
|
+
});
|
867
|
+
}
|
868
|
+
});
|
869
|
+
});
|
870
|
+
}
|
871
|
+
|
872
|
+
// Add selector listeners
|
873
|
+
if (!self.selectorChangedData[selector]) {
|
874
|
+
self.selectorChangedData[selector] = [];
|
875
|
+
}
|
876
|
+
|
877
|
+
self.selectorChangedData[selector].push(callback);
|
878
|
+
|
879
|
+
return self;
|
880
|
+
},
|
881
|
+
|
882
|
+
getScrollContainer: function() {
|
883
|
+
var scrollContainer, node = this.dom.getRoot();
|
884
|
+
|
885
|
+
while (node && node.nodeName != 'BODY') {
|
886
|
+
if (node.scrollHeight > node.clientHeight) {
|
887
|
+
scrollContainer = node;
|
888
|
+
break;
|
889
|
+
}
|
890
|
+
|
891
|
+
node = node.parentNode;
|
892
|
+
}
|
893
|
+
|
894
|
+
return scrollContainer;
|
895
|
+
},
|
896
|
+
|
897
|
+
scrollIntoView: function(elm, alignToTop) {
|
898
|
+
var y, viewPort, self = this, dom = self.dom, root = dom.getRoot(), viewPortY, viewPortH, offsetY = 0;
|
899
|
+
|
900
|
+
function getPos(elm) {
|
901
|
+
var x = 0, y = 0;
|
902
|
+
|
903
|
+
var offsetParent = elm;
|
904
|
+
while (offsetParent && offsetParent.nodeType) {
|
905
|
+
x += offsetParent.offsetLeft || 0;
|
906
|
+
y += offsetParent.offsetTop || 0;
|
907
|
+
offsetParent = offsetParent.offsetParent;
|
908
|
+
}
|
909
|
+
|
910
|
+
return {x: x, y: y};
|
911
|
+
}
|
912
|
+
|
913
|
+
if (!NodeType.isElement(elm)) {
|
914
|
+
return;
|
915
|
+
}
|
916
|
+
|
917
|
+
if (alignToTop === false) {
|
918
|
+
offsetY = elm.offsetHeight;
|
919
|
+
}
|
920
|
+
|
921
|
+
if (root.nodeName != 'BODY') {
|
922
|
+
var scrollContainer = self.getScrollContainer();
|
923
|
+
if (scrollContainer) {
|
924
|
+
y = getPos(elm).y - getPos(scrollContainer).y + offsetY;
|
925
|
+
viewPortH = scrollContainer.clientHeight;
|
926
|
+
viewPortY = scrollContainer.scrollTop;
|
927
|
+
if (y < viewPortY || y + 25 > viewPortY + viewPortH) {
|
928
|
+
scrollContainer.scrollTop = y < viewPortY ? y : y - viewPortH + 25;
|
929
|
+
}
|
930
|
+
|
931
|
+
return;
|
932
|
+
}
|
933
|
+
}
|
934
|
+
|
935
|
+
viewPort = dom.getViewPort(self.editor.getWin());
|
936
|
+
y = dom.getPos(elm).y + offsetY;
|
937
|
+
viewPortY = viewPort.y;
|
938
|
+
viewPortH = viewPort.h;
|
939
|
+
if (y < viewPort.y || y + 25 > viewPortY + viewPortH) {
|
940
|
+
self.editor.getWin().scrollTo(0, y < viewPortY ? y : y - viewPortH + 25);
|
941
|
+
}
|
942
|
+
},
|
943
|
+
|
944
|
+
placeCaretAt: function(clientX, clientY) {
|
945
|
+
this.setRng(RangeUtils.getCaretRangeFromPoint(clientX, clientY, this.editor.getDoc()));
|
946
|
+
},
|
947
|
+
|
948
|
+
_moveEndPoint: function(rng, node, start) {
|
949
|
+
var root = node, walker = new TreeWalker(node, root);
|
950
|
+
var nonEmptyElementsMap = this.dom.schema.getNonEmptyElements();
|
951
|
+
|
952
|
+
do {
|
953
|
+
// Text node
|
954
|
+
if (node.nodeType == 3 && trim(node.nodeValue).length !== 0) {
|
955
|
+
if (start) {
|
956
|
+
rng.setStart(node, 0);
|
957
|
+
} else {
|
958
|
+
rng.setEnd(node, node.nodeValue.length);
|
959
|
+
}
|
960
|
+
|
961
|
+
return;
|
962
|
+
}
|
963
|
+
|
964
|
+
// BR/IMG/INPUT elements but not table cells
|
965
|
+
if (nonEmptyElementsMap[node.nodeName] && !/^(TD|TH)$/.test(node.nodeName)) {
|
966
|
+
if (start) {
|
967
|
+
rng.setStartBefore(node);
|
968
|
+
} else {
|
969
|
+
if (node.nodeName == 'BR') {
|
970
|
+
rng.setEndBefore(node);
|
971
|
+
} else {
|
972
|
+
rng.setEndAfter(node);
|
973
|
+
}
|
974
|
+
}
|
975
|
+
|
976
|
+
return;
|
977
|
+
}
|
978
|
+
|
979
|
+
// Found empty text block old IE can place the selection inside those
|
980
|
+
if (Env.ie && Env.ie < 11 && this.dom.isBlock(node) && this.dom.isEmpty(node)) {
|
981
|
+
if (start) {
|
982
|
+
rng.setStart(node, 0);
|
983
|
+
} else {
|
984
|
+
rng.setEnd(node, 0);
|
985
|
+
}
|
986
|
+
|
987
|
+
return;
|
988
|
+
}
|
989
|
+
} while ((node = (start ? walker.next() : walker.prev())));
|
990
|
+
|
991
|
+
// Failed to find any text node or other suitable location then move to the root of body
|
992
|
+
if (root.nodeName == 'BODY') {
|
993
|
+
if (start) {
|
994
|
+
rng.setStart(root, 0);
|
995
|
+
} else {
|
996
|
+
rng.setEnd(root, root.childNodes.length);
|
997
|
+
}
|
998
|
+
}
|
999
|
+
},
|
1000
|
+
|
1001
|
+
destroy: function() {
|
1002
|
+
this.win = null;
|
1003
|
+
this.controlSelection.destroy();
|
1004
|
+
}
|
1005
|
+
};
|
1006
|
+
|
1007
|
+
return Selection;
|
1008
|
+
});
|