install tinymce 4.1.7 with Bower

refs CNVS-11523

this doesn't make use of 4.1.7, just gets it into the
repo so we have a stable installed version

Change-Id: Id5dd09574d1f74ec33ad373998510181deac7f28
Reviewed-on: https://gerrit.instructure.com/49996
Tested-by: Jenkins
Reviewed-by: Jacob Fugal <jacob@instructure.com>
QA-Review: Ethan Vizitei <evizitei@instructure.com>
Product-Review: Ethan Vizitei <evizitei@instructure.com>
This commit is contained in:
Ethan Vizitei 2015-03-06 12:57:49 -07:00
parent 7b3a02cb69
commit c6d219029e
127 changed files with 88780 additions and 1 deletions

View File

@ -19,6 +19,7 @@
"ic-sortable": "0.0.2",
"react": "0.12.2",
"react-router": "0.11.6",
"react-modal": "0.0.7"
"react-modal": "0.0.7",
"tinymce": "4.1.7"
}
}

View File

@ -0,0 +1,30 @@
{
"name": "tinymce",
"version": "4.1.7",
"description": "Web based JavaScript HTML WYSIWYG editor control.",
"license": "http://www.tinymce.com/license",
"keywords": [
"editor",
"wysiwyg",
"tinymce",
"richtext",
"javascript",
"html"
],
"homepage": "http://www.tinymce.com",
"main": "tinymce.min.js",
"ignore": [
"readme.md",
"composer.json",
"package.json"
],
"_release": "4.1.7",
"_resolution": {
"type": "version",
"tag": "4.1.7",
"commit": "555fcfa1a09e93732a51950ba3d731050f31d39a"
},
"_source": "git://github.com/tinymce/tinymce-dist.git",
"_target": "4.1.7",
"_originalSource": "tinymce"
}

View File

@ -0,0 +1,3 @@
composer.json
bower.json
readme.md

View File

@ -0,0 +1,21 @@
{
"name": "tinymce",
"version": "4.1.7",
"description": "Web based JavaScript HTML WYSIWYG editor control.",
"license": "http://www.tinymce.com/license",
"keywords": [
"editor",
"wysiwyg",
"tinymce",
"richtext",
"javascript",
"html"
],
"homepage": "http://www.tinymce.com",
"main": "tinymce.min.js",
"ignore": [
"readme.md",
"composer.json",
"package.json"
]
}

View File

@ -0,0 +1,710 @@
Version 4.1.7 (2014-11-27)
Added HTML5 schema support for srcset, source and picture. Patch contributed by mattheu.
Added new cache_suffix setting to enable cache busting by producing unique urls.
Added new paste_convert_word_fake_lists option to enable users to disable the fake lists convert logic.
Fixed so advlist style changes adds undo levels for each change.
Fixed bug where WebKit would sometimes produce an exception when the autolink plugin where looking for URLs.
Fixed bug where IE 7 wouldn't be rendered properly due to to aggressive css compression.
Fixed bug where DomQuery wouldn't accept window as constructor element.
Fixed bug where the color picker in 3.x dialogs wouldn't work properly. Patch contributed by Callidior.
Fixed bug where the image plugin wouldn't respect the document_base_url.
Fixed bug where the jQuery plugin would fail to append to elements named array prototype names.
Version 4.1.6 (2014-10-08)
Fixed bug with clicking on the scrollbar of the iframe would cause a JS error to be thrown.
Fixed bug where null would produce an exception if you passed it to selection.setRng.
Fixed bug where Ctrl/Cmd+Tab would indent the current list item if you switched tabs in the browser.
Fixed bug where pasting empty cells from Excel would result in a broken table.
Fixed bug where it wasn't possible to switch back to default list style type.
Fixed issue where the select all quirk fix would fire for other modifiers than Ctrl/Cmd combinations.
Replaced jake with grunt since it is more mainstream and has better plugin support.
Version 4.1.5 (2014-09-09)
Fixed bug where sometimes the resize rectangles wouldn't properly render on images on WebKit/Blink.
Fixed bug in list plugin where delete/backspace would merge empty LI elements in lists incorrectly.
Fixed bug where empty list elements would result in empty LI elements without it's parent container.
Fixed bug where backspace in empty caret formated element could produce an type error exception of Gecko.
Fixed bug where lists pasted from word with a custom start index above 9 wouldn't be properly handled.
Fixed bug where tabfocus plugin would tab out of the editor instance even if the default action was prevented.
Fixed bug where tabfocus wouldn't tab properly to other adjacent editor instances.
Fixed bug where the DOMUtils setStyles wouldn't properly removed or update the data-mce-style attribute.
Fixed bug where dialog select boxes would be placed incorrectly if document.body wasn't statically positioned.
Fixed bug where pasting would sometimes scroll to the top of page if the user was using the autoresize plugin.
Fixed bug where caret wouldn't be properly rendered by Chrome when clicking on the iframes documentElement.
Fixed so custom images for menubutton/splitbutton can be provided. Patch contributed by Naim Hammadi.
Fixed so the default action of windows closing can be prevented by blocking the default action of the close event.
Fixed so nodeChange and focus of the editor isn't automatically performed when opening sub dialogs.
Version 4.1.4 (2014-08-21)
Added new media_filter_html option to media plugin that blocks any conditional comments, scripts etc within a video element.
Added new content_security_policy option allows you to set custom policy for iframe contents. Patch contributed by Francois Chagnon.
Fixed bug where activate/deactivate events wasn't firing properly when switching between editors.
Fixed bug where placing the caret on iOS was difficult due to a WebKit bug with touch events.
Fixed bug where the resize helper wouldn't render properly on older IE versions.
Fixed bug where resizing images inside tables on older IE versions would sometimes fail depending mouse position.
Fixed bug where editor.insertContent would produce an exception when inserting select/option elements.
Fixed bug where extra empty paragraphs would be produced if block elements where inserted inside span elements.
Fixed bug where the spellchecker menu item wouldn't be properly checked if spell checking was started before it was rendered.
Fixed bug where the DomQuery filter function wouldn't remove non elements from collection.
Fixed bug where document with custom document.domain wouldn't properly render the editor.
Fixed bug where IE 8 would throw exception when trying to enter invalid color values into colorboxes.
Fixed bug where undo manager could incorrectly add an extra undo level when custom resize handles was removed.
Fixed bug where it wouldn't be possible to alter cell properties properly on table cells on IE 8.
Fixed so the color picker button in table dialog isn't shown unless you include the colorpicker plugin or add your own custom color picker.
Fixed so activate/deactivate events fire when windowManager opens a window since.
Fixed so the table advtab options isn't separated by an underscore to normalize naming with image_advtab option.
Fixed so the table cell dialog has proper padding when the advanced tab in disabled.
Version 4.1.3 (2014-07-29)
Added event binding logic to tinymce.util.XHR making it possible to override headers and settings before any request is made.
Fixed bug where drag events wasn't fireing properly on older IE versions since the event handlers where bound to document.
Fixed bug where drag/dropping contents within the editor on IE would force the contents into plain text mode even if it was internal content.
Fixed bug where IE 7 wouldn't open menus properly due to a resize bug in the browser auto closing them immediately.
Fixed bug where the DOMUtils getPos logic wouldn't produce a valid coordinate inside the body if the body was positioned non static.
Fixed bug where the element path and format state wasn't properly updated if you had the wordcount plugin enabled.
Fixed bug where a comment at the beginning of source would produce an exception in the formatter logic.
Fixed bug where setAttrib/getAttrib on null would throw exception together with any hooked attributes like style.
Fixed bug where table sizes wasn't properly retained when copy/pasting on WebKit/Blink.
Fixed bug where WebKit/Blink would produce colors in RGB format instead of the forced HEX format when deleting contents.
Fixed bug where the width attribute wasn't updated on tables if you changed the size inside the table dialog.
Fixed bug where control selection wasn't properly handled when the caret was placed directly after an image.
Fixed bug where selecting the contents of table cells using the selection.select method wouldn't place the caret properly.
Fixed bug where the selection state for images wasn't removed when placing the caret right after an image on WebKit/Blink.
Fixed bug where all events wasn't properly unbound when and editor instance was removed or destroyed by some external innerHTML call.
Fixed bug where it wasn't possible or very hard to select images on iOS when the onscreen keyboard was visible.
Fixed so auto_focus can take a boolean argument this will auto focus the last initialized editor might be useful for single inits.
Fixed so word auto detect lists logic works better for faked lists that doesn't have specific markup.
Fixed so nodeChange gets fired on mouseup as it used to before 4.1.1 we optimized that event to fire less often.
Removed the finish menu item from spellchecker menu since it's redundant you can stop spellchecking by toggling menu item or button.
Version 4.1.2 (2014-07-15)
Added offset/grep to DomQuery class works basically the same as it's jQuery equivalent.
Fixed bug where backspace/delete or setContent with an empty string would remove header data when using the fullpage plugin.
Fixed bug where tinymce.remove with a selector not matching any editors would remove all editors.
Fixed bug where resizing of the editor didn't work since the theme was calling setStyles instead of setStyle.
Fixed bug where IE 7 would fail to append html fragments to iframe document when using DomQuery.
Fixed bug where the getStyle DOMUtils method would produce an exception if it was called with null as it's element.
Fixed bug where the paste plugin would remove the element if the none of the paste_webkit_styles rules matched the current style.
Fixed bug where contextmenu table items wouldn't work properly on IE since it would some times fire an incorrect selection change.
Fixed bug where the padding/border values wasn't used in the size calculation for the body size when using autoresize. Patch contributed by Matt Whelan.
Fixed bug where conditional word comments wouldn't be properly removed when pasting plain text.
Fixed bug where resizing would sometime fail on IE 11 when the mouseup occurred inside the resizable element.
Fixed so the iframe gets initialized without any inline event handlers for better CSP support. Patch contributed by Matt Whelan.
Fixed so the tinymce.dom.Sizzle is the latest version of sizzle this resolves the document context bug.
Version 4.1.1 (2014-07-08)
Fixed bug where pasting plain text on some WebKit versions would result in an empty line.
Fixed bug where resizing images inside tables on IE 11 wouldn't work properly.
Fixed bug where IE 11 would sometimes throw "Invalid argument" exception when editor contents was set to an empty string.
Fixed bug where document.activeElement would throw exceptions on IE 9 when that element was hidden or removed from dom.
Fixed bug where WebKit/Blink sometimes produced br elements with the Apple-interchange-newline class.
Fixed bug where table cell selection wasn't properly removed when copy/pasting table cells.
Fixed bug where pasting nested list items from Word wouldn't produce proper semantic nested lists.
Fixed bug where right clicking using the contextmenu plugin on WebKit/Blink on Mac OS X would select the target current word or line.
Fixed bug where it wasn't possible to alter table cell properties on IE 8 using the context menu.
Fixed bug where the resize helper wouldn't be correctly positioned on older IE versions.
Fixed bug where fullpage plugin would produce an error if you didn't specify a doctype encoding.
Fixed bug where anchor plugin would get the name/id of the current element even if it wasn't anchor element.
Fixed bug where visual aids for tables wouldn't be properly disabled when changing the border size.
Fixed bug where some control selection events wasn't properly fired on older IE versions.
Fixed bug where table cell selection on older IE versions would prevent resizing of images.
Fixed bug with paste_data_images paste option not working properly on modern IE versions.
Fixed bug where custom elements with underscores in the name wasn't properly parsed/serialized.
Fixed bug where applying inline formats to nested list elements would produce an incorrect formatting result.
Fixed so it's possible to hide items from elements path by using preventDefault/stopPropagation.
Fixed so inline mode toolbar gets rendered right aligned if the editable element positioned to the documents right edge.
Fixed so empty inline elements inside empty block elements doesn't get removed if configured to be kept intact.
Fixed so DomQuery parentsUntil/prevUntil/nextUntil supports selectors/elements/filters etc.
Fixed so legacyoutput plugin overrides fontselect and fontsizeselect controls and handles font elements properly.
Version 4.1.0 (2014-06-18)
Added new file_picker_callback option to replace the old file_browser_callback the latter will still work though.
Added new custom colors to textcolor plugin will be displayed if a color picker is provided also shows the latest colors.
Added new color_picker_callback option to enable you to add custom color pickers to the editor.
Added new advanced tabs to table/cell/row dialogs to enable you to select colors for border/background.
Added new colorpicker plugin that lets you select colors from a hsv color picker.
Added new tinymce.util.Color class to handle color parsing and converting.
Added new colorpicker UI widget element lets you add a hsv color picker to any form/window.
Added new textpattern plugin that allows you to use markdown like text patterns to format contents.
Added new resize helper element that shows the current width & height while resizing.
Added new "once" method to Editor and EventDispatcher enables since callback execution events.
Added new jQuery like class under tinymce.dom.DomQuery it's exposed on editor instances (editor.$) and globally under (tinymce.$).
Fixed so the default resize method for images are proportional shift/ctrl can be used to make an unproportional size.
Fixed bug where the image_dimensions option of the image plugin would cause exceptions when it tried to update the size.
Fixed bug where table cell dialog class field wasn't properly updated when editing an a table cell with an existing class.
Fixed bug where Safari on Mac would produce webkit-fake-url for pasted images so these are now removed.
Fixed bug where the nodeChange event would get fired before the selection was changed when clicking inside the current selection range.
Fixed bug where valid_classes option would cause exception when it removed internal prefixed classes like mce-item-.
Fixed bug where backspace would cause navigation in IE 8 on an inline element and after a caret formatting was applied.
Fixed so placeholder images produced by the media plugin gets selected when inserted/edited.
Fixed so it's possible to drag in images when the paste_data_images option is enabled. Might be useful for mail clients.
Fixed so images doesn't get a width/height applied if the image_dimensions option is set to false useful for responsive contents.
Fixed so it's possible to pass in an optional arguments object for the nodeChanged function to be passed to all nodechange event listeners.
Fixed bug where media plugin embed code didn't update correctly.
Version 4.0.28 (2014-05-27)
Fixed critical issue with empty urls producing an exception when converted into absolute urls due to resent bug fix in tinymce.util.URI.
Version 4.0.27 (2014-05-27)
Added support for definition lists to lists plugin and enter key logic. This can now created by the format menu.
Added cmd option for the style_formats menu enables you to toggle commands on/off using the formats menu for example lists.
Added definition lists to visualblocks plugin so these are properly visualized like other list elements.
Added new paste_merge_formats option that reduces the number of nested text format elements produced on paste. Enabled by default.
Added better support for nested link_list/image_list menu items each item can now have a "menu" item with subitems.
Added "Add to Dictionary" support to spellchecker plugin when the backend tells that this feature is available.
Added new table_default_attributes/table_default_styles options patch contributed by Dan Villiom Podlaski Christiansen.
Added new table_class_list/table_cell_class_list/table_row_class_list options to table plugin.
Added new invalid_styles/valid_classes options to better control what gets returned for the style/class attribute.
Added new file_browser_callback_types option that allows you to specify where to display the picker based on dialog type.
Fixed so the selected state is properly handled on nested menu items in listboxes patch contributed by Jelle Kralt.
Fixed so the invisiblity css value for TinyMCE gets set to inherit instead of visible to better support dialog scripts like reveal.
Fixed bug where Gecko would remove anchors when pasting since the their default built in logic removes empty nodes.
Fixed bug where it wasn't possible to paste on Chrome Andoid since it doesn't properly support the Clipboard API yet.
Fixed bug where user defined type attribute value of text/javascript didn't get properly serialized.
Fixed bug where space in span elements would removed when the element was considered empty.
Fixed bug where the undo/redo button states didn't change if you removed all undo levels using undoManager.clear.
Fixed bug where unencoded links inside query strings or hash values would get processed by the relative urls logic.
Fixed bug where contextmenu would automatically close in inline editing mode on Firefox running on Mac.
Fixed bug where Gecko/IE would produce multiple BR elements when forced_root_block was set to false and a table was the last child of body.
Fixed bug where custom queryCommandState handlers didn't properly handle boolean states.
Fixed bug where auto closing float panels link menus wasn't automatically closed when the window was resized.
Fixed bug where the image plugin wouldn't update image dimensions when the current image was changed using the image_list select box.
Fixed bug with paste plugin not properly removing paste bin on Safari Mac when using the cmd+shift+v keyboard command.
Fixed bug where the paste plugin wouln't properly strip trailing br elements under very specific scenarios.
Fixed bug where enter key wouldn't properly place the caret on Gecko when pressing enter in a text block with a br ended line inside.
Fixed bug where Safari Mac shortcuts like Cmd+Opt+L didn't get passed through to the browser due to a Quirks fix.
Fixed so plain text mode works better when it converts rich text to plain text when pasting from for example Word.
Fixed so numeric keycodes can be used in the shortcut format enabling support for any key to be specified.
Fixed so table cells can be navigated with tab key and new rows gets automatically added when you are at the last cell.
Fixed bug where formatting before cursor gets removed when toggled off for continued content.
Version 4.0.26 (2014-05-06)
Fixed bug in media plugin where changing existing url did not use media regex patterns to create protocol neutral url.
Fixed bug where selection wasn't properly restored on IE 11 due to a browser bug with Element.contains.
Version 4.0.25 (2014-04-30)
Fixed bug where it wasn't possible to submit forms with editor instances on WebKit/Blink.
Version 4.0.24 (2014-04-30)
Added new event_root setting for inline editors. Lets you bind all editor events on a parent container.
Fixed bug where show/hide/isHidden didn't work properly for inline editor instances.
Fixed bug where preview plugin dialog didn't handle relative urls properly.
Fixed bug where the autolink plugin would remove the trailing space after an inserted link.
Fixed bug in paste plugin where pasting in a page with scrollbars would scroll to top of page in webkit browsers.
Fixed bug where the paste plugin on WebKit would remove styles from pasted source code with style attributes.
Fixed so image_list/link_list can be a function that allows custom async calls to populate these lists.
Version 4.0.23 (2014-04-24)
Added isSameOrigin method to tinymce.util.URI it handles default protocol port numbers better. Patch contributed by Matt Whelan.
Fixed bug where IE 11 would add br elements to the end of the editor body element each time it was shown/hidden.
Fixed bug where the autolink plugin would produce an index out of range exception for some very specific HTML.
Fixed bug where the charmap plugin wouldn't properly insert non breaking space characters when selected.
Fixed bug where pasting from Excel 2011 on Mac didn't produce a proper table when using the paste plugin.
Fixed bug where drag/dropping inside a table wouldn't properly end the table cell selection.
Fixed bug where drag/dropping images within tables on Safari on Mac wouldn't work properly.
Fixed bug where editors couldn't be re-initialized if they where externally destroyed.
Fixed bug where inline editors would produce a range index exception when clicking on buttons like bold.
Fixed bug where the preview plugin wouldn't properly handle non encoded upper UTF-8 characters.
Fixed so document.currentScript is used when detecting the current script location. Patch contributed by Mickael Desgranges.
Fixed issue with the paste_webkit_styles option so is disabled by default since it might produce a lot of extra styles.
Version 4.0.22 (2014-04-16)
Added lastLevel to BeforeAddUndo level event so it's easier to block undo level creation based.
Fixed so multiple list elements can be indented properly. Patch contributed by Dan Villiom Podlaski Christiansen.
Fixed bug where the selection would be at the wrong location sometimes for inline editor instances.
Fixed bug where drag/dropping content into an inline editor would fail on WebKit/Blink.
Fixed bug where table grid wouldn't work properly when the UI was rendered in for RTL mode.
Fixed bug where range normalization wouldn't handle mixed contentEditable nodes properly.
Fixed so the media plugin doesn't override the existing element rules you now need to manually whitelist non standard attributes.
Fixed so old language packs get properly loaded when the new longer language code format is used.
Fixed so all track changes junk such as comments, deletes etc gets removed when pasting from Word.
Fixed so non image data urls is blocked by default since they might contain scripts.
Fixed so it's possible to import styles from the current page stylesheets into an inline editor by using the importcss_file_filter.
Fixed bug where the spellchecker plugin wouldn't add undo levels for each suggestion replacement.
Reworked the default spellchecker RPC API to match the new PHP Spellchecker package. Fallback documented in the TinyMCE docs.
Version 4.0.21 (2014-04-01)
Added new getCssText method to formatter to get the preview css text value for a format to be used in UI.
Added new table_grid option that allows you to disable the table grid and use a dialog.
Added new image_description, image_dimensions options to image plugin. Patch contributed by Pat O'Neill.
Added new media_alt_source, media_poster, media_dimensions options to media plugin. Patch contributed by Pat O'Neill.
Added new ability to specify high/low dpi versions custom button images for retina displays.
Added new getWindows method to WindowManager makes it easier to control the currently opened windows.
Added new paste_webkit_styles option to paste plugin to control the styles that gets retained on WebKit.
Added preview of classes for the selectboxes used by the link_class_list/image_class_list options.
Added support for Sauce Labs browser testing using the new saucelabs-tests build target.
Added title input field to link dialog for a11y reasons can be disabled by using the link_title option.
Fixed so the toolbar option handles an array as input for multiple toolbar rows.
Fixed so the editor renders in XHTML mode apparently some people still use this rendering mode.
Fixed so icons gets rendered better on Firefox on Mac OS X by applying -moz-osx-font-smoothing.
Fixed so the auto detected external media sources produced protocol relative urls. Patch contributed by Pat O'Neill.
Fixed so it's possible to update the text of a button after it's been rendered to page DOM.
Fixed bug where iOS 7.1 Safari would open linked when images where inserted into links.
Fixed bug where IE 11 would scroll to the top of inline editable elements when applying formatting.
Fixed bug where tabindex on elements within the editor contents would cause issues on some browsers.
Fixed bug where link text wouldn't be properly updated in gecko if you changed an existing link.
Fixed bug where it wasn't possible to close dialogs with the escape key if the focus was inside a textbox.
Fixed bug where Gecko wouldn't paste rich text contents from Word or other similar word processors.
Fixed bug where binding events after the control had been rendered could fail to produce a valid delegate.
Fixed bug where IE 8 would throw and error when removing editors with a cross domain content_css setting.
Fixed bug where IE 9 wouldn't be able to select text after an editor instance with caret focus was removed.
Fixed bug where the autoresize plugin wouldn't resize the editor if you inserted huge images.
Fixed bug where multiple calls to the same init would produce extra editor instances.
Fixed bug where fullscreen toggle while having the autoresize plugin enabled wouldn't produce scrollbars.
Fixed so screen readers use a dialog instead of the grid for inserting tables.
Fixed so Office 365 Word contents gets filtered the same way as content from desktop Office.
Fixed so it's possible to override the root container for UI elements defaults to document.body.
Fixed bug where tabIndex is set to -1 on inline editable elements. It now keeps the existing tabIndex intact.
Fixed issue where the UndoManager transact method couldn't be nested since it only had one lock.
Fixed issue where headings/heading where labeled incorrectly as headers/header.
Version 4.0.20 (2014-03-18)
Fixed so all unit tests can be executed in a headless phantomjs instance for CI testing.
Fixed so directionality setting gets applied to the preview dialog as well as the editor body element.
Fixed a performance issue with the "is" method in DOMUtils. Patch contributed by Paul Bosselaar.
Fixed bug where paste plugin wouldn't paste plain text properly when pasting using browser menus.
Fixed bug where focusable SVG elements would throw an error since className isn't a proper string.
Fixed bug where the preview plugin didn't properly support the document_base_url setting.
Fixed bug where the focusedEditor wouldn't be set to null when that editor was removed.
Fixed bug where Gecko would throw an exception when editors where removed.
Fixed bug where the FocusManager wouldn't handle selection restoration properly on older IE versions.
Fixed bug where the searchreplace plugin would produce an exception on very specific multiple searches.
Fixed bug where some events wasn't properly unbound when all editors where removed from page.
Fixed bug where tapping links on iOS 7.1 would open the link instead of placing the caret inside.
Fixed bug where holding the finger down on iOS 7.1 would open the link/image callout menu.
Fixed so the jQuery plugin returns null when getting the the tinymce instance of an element before it's initialized.
Fixed so selection normalization gets executed more often to reduce incorrect UI states on Gecko.
Fixed so the default action of closing the window on a form submission can be prevented using "preventDefault".
Version 4.0.19 (2014-03-11)
Added support for CSS selector expressions in object_resizing option. Allows you to control what to resize.
Added addToTop compatibility to compat3x plugin enables more legacy 3.x plugins to work properly.
Fixed bug on IE where it wasn't possible to align images when they where floated left.
Fixed bug where the indent/outdent buttons was enabled though readonly mode was enabled.
Fixed bug where the nodeChanged event was fired when readonly mode was enabled.
Fixed bug where events like blur could be fired to editor instances that where manually removed on IE 11.
Fixed bug where IE 11 would move focus to menubar/toolbar when using the tab key in a form with an editor.
Fixed bug where drag/drop in Safari on Mac didn't work properly due to lack of support for modern dataTransfer object.
Fixed bug where the remove event wasn't properly executed when the editor instances where removed.
Fixed bug where the selection change handler on inline editors would fail if the editor instance was removed.
Version 4.0.18 (2014-02-27)
Fixed bug where images would get class false/undefined when initially created.
Version 4.0.17 (2014-02-26)
Added much better wai-aria accessibility support when it comes to keyboard navigation of complex UI controls.
Added dfn,code,samp,kbd,var,cite,mark,q elements to the default remove formats list. Patch contributed by Naim Hammadi.
Added var,cite,dfn,code,mark,q,sup,sub to the list of elements that gets cloned on enter. Patch contributed by Naim Hammadi.
Added new visual_anchor_class option to specify a custom class for inline anchors. Patch contributed by Naim Hammadi.
Added support for paste_data_images on WebKit/Blink when the user pastes image data.
Added support for highlighting the video icon when a video is added that produces an iframe. Patch contributed by monkeydiane.
Added image_class_list/link_class_list options to image/link dialogs to let the user select classes.
Fixed bug where the ObjectResizeStart event didn't get fired properly by the ControlSelection class.
Fixed bug where the autolink plugin would steal focus when loaded on IE 9+.
Fixed bug where the editor save method would remove the current selection when called on an inline editor.
Fixed bug where the formatter would merge span elements with parent bookmarks if an id format was used.
Fixed bug where WebKit/Blink browsers would scroll to the top of the editor when pasting into an empty element.
Fixed bug where removing the editor would cause an error about wrong document on IE 11 under specific circumstances.
Fixed bug where Gecko would place the caret at an incorrect location when using backspace.
Fixed bug where Gecko would throw "Wrong Document Error" for ranges that pointing to removed nodes.
Fixed bug where it wasn't possible to properly update the title and encoding properties in the fullpage plugin.
Fixed bug where paste plugin would produce an extra undo level on IE.
Fixed bug where the formatter would apply inline formatting outside the current word in if the selection was collapsed.
Fixed bug where it wasn't possible to delete tables on Chrome if you placed the selection within all the contents of the table.
Fixed bug where older IE versions wouldn't properly insert contents into table cells when editor focus was lost.
Fixed bug where older IE versions would fire focus/blur events even though the editor focus didn't change.
Fixed bug where IE 11 would add two trailing BR elements to the editor iframe body if the editor was hidden.
Fixed bug where the visualchars plugin wouldn't display non breaking spaces if they where inserted while the state was enabled.
Fixed bug where the wordcount plugin would be very slow some HTML where to much backtracking occurred.
Fixed so pagebreak elements in the editor breaks pages when printing. Patch contributed by penc.
Fixed so UndoManager events pass though the original event that created the undo level such as a keydown, blur etc.
Fixed so the inserttime button is callsed insertdatetime the same as the menu item and plugin name.
Fixed so the word count plugin handles counting properly on most languages on the planet.
Fixed bug where the auroreize plugin would throw an error if the editor was manually removed within a few seconds.
Fixed bug where the image dialog would get stuck if the src was removed. Patch contribued by monkeydiane.
Fixed bug where there is an extra br tag for IE 9/10 that isn't needed. Patch contributed by monkeydiane.
Fixed bug where drag/drop in a scrolled editor would fail since it didn't use clientX/clientY cordinates. Patch contributed by annettem.
Version 4.0.16 (2014-01-31)
Fixed bug where the editor wouldn't be properly rendered on IE 10 depending on the document.readyState.
Version 4.0.15 (2014-01-31)
Fixed bug where paste in inline mode would produce an exception if the contents was pasted inside non overflow element.
Version 4.0.14 (2014-01-30)
Fixed a bug in the image plugin where images couldn't be inserted if the image_advtab option wasn't set to true.
Version 4.0.13 (2014-01-30)
Added language selection menu to spellchecker button similar to the 3.x functionality. Patch contributed by threebytesfull.
Added new style_formats_merge option that enables you to append to the default formats instead of replaceing them. Patch contributed by PacificMorrowind.
Fixed bug where the DOMUtils getPos API function didn't properly handle the location of the root element. Patch contributed by Andrew Ozz.
Fixed bug where the spellchecker wouldn't properly place the spellchecker suggestions menu. Patch contributed by Andrew Ozz.
Fixed bug where the tabfocus plugin would prevent the user from suing Ctrl+Tab, Patch contributed by Andrew Ozz.
Fixed bug where table resize handles could sometimes be added to elements out side the editable inline element.
Fixed bug where the inline mode editor UI would render incorrectly when the stylesheets didn't finish loading on Chrome.
Fixed bug where IE 8 would insert the image outside the editor unless it was focused first.
Fixed bug where older IE versions would throw an exception on drag/drop since they don't support modern dataTransfer API.
Fixed bug where the blockquote button text wasn't properly translated since it had the wrong English key.
Fixed bug where the importcss plugin didn't import a.class rules properly as selector formats.
Fixed bug where the combobox control couldn't be disabled or set to a specific character size initially.
Fixed bug where the FormItem didn't inherit the disabled state from the control to be wrapped.
Fixed bug where adding a TinyMCE instance within a TinyMCE dialog wouldn't properly delegate the events.
Fixed bug where any overflow parent containers would automatically scroll to the left when pasting in Chrome.
Fixed bug where IE could throw an error when search/replacing contents due to an invalid selection being returned.
Fixed bug where WebKit would fire focus/blur events incorrectly if the editor was empty due to a WebKit focus bug.
Fixed bug where WebKit/Blink would scroll to the top of editor if the height was more than the viewport height.
Fixed bug where blurring and removing the editor could cause an exteption to be thrown by the FocusManager.
Fixed bug where the media plugin would override specified dimensions for url pattern matches. Patch contributed by penc.
Fixed bug where the autoresize plugin wouldn't take margins into account when calculating the body size. Patch contributed by lepoltj.
Fixed bug where the image plugin would throw errors some times on IE 8 when it preloaded the image to get it's dimensions.
Fixed bug where the image plugin wouldn't update the style if the user closed the dialog before focusing out. Patch contributed by jonparrott.
Fixed bug where bindOnReady in EventUtils wouldn't work properly for some edge cases on older IE versions. Patch contributed by Godefroy.
Fixed bug where image selector formats wasn't properly handled by the importcss plugin.
Fixed bug where the dirty state of the editor wasn't set when editing an existing link URL.
Fixed bug where it wasn't possible to prevent paste from happening by blocking the default behavior when the paste plugin was enabled.
Fixed bug where text to display in the insert/edit link dialog wouldn't be properly entity encoded.
Fixed bug where Safari 7 on Mac OS X would delete contents if you pressed Cmd+C since it passes out a charCode for the event.
Fixed bug where bound drop events inside inline editors would get fired on all editor instances instead of the specific instance.
Fixed bug where images outlined selection border would be clipped when the autoresize plugin was enabled.
Fixed bug where image dimension constrains proportions wouldn't work properly if you altered a value and immediately clicked the submit button.
Fixed so you don't need to set language option to false when specifying a custom language_url.
Fixed so the link dialog "text to display" field gets automatically hidden if the selection isn't text contents. Patch contributed by Godefroy.
Fixed so the none option for the target field in the link dialog gets excluded when specifiying the target_list config option.
Fixed so outline styles are displayed by default in the formats preview. Patch contributed by nhammadi.
Fixed so the max characters for width/height is more than 3 in the media and image dialogs.
Fixed so the old mceSpellCheck command toggles the spellchecker on/off.
Fixed so the setupeditor event is fired before the setup callback setting to ease up compatibility with 3.x.
Fixed so auto url link creation in IE 9+ is disabled by default and re-enabled by the autolink plugin.
Removed the custom scrollbars for WebKit since the default browser scrollbars looks a lot better now days.
Version 4.0.12 (2013-12-18)
Added new media_scripts option to the media plugin. This makes it possible to embed videos using script elements.
Fixed bug where WebKit/Blink would produce random span elements and styles when deleting contents inside the editor.
Fixed bug where WebKit/Blink would produce span elements out of link elements when they where removed by the unlink command.
Fixed bug where div block formats in inline mode where applied to all paragraphs within the editor.
Fixed bug where div blocks where marked as an active format in inline mode when doing non collapsed selections.
Fixed bug where the importcss plugin wouldn't append styles if the style_formats option was configured.
Fixed bug where the importcss plugin would import styles into groups multiple times for different format menus.
Fixed bug where the paste plugin wouldn't properly remove the paste bin element on IE if a tried to paste a file.
Fixed bug where selection normalization wouldn't properly handle cases where a range point was after a element node.
Fixed bug where the default time format for the inserttime split button wasn't the first item in the list.
Fixed bug where the default text for the formatselect control wasn't properly translated by the language pack.
Fixed bug where links would be inserted incorrectly when auto detecting absolute urls/emails links in inline mode.
Fixed bug where IE 11 would insert contents in the wrong order due to focus/blur async problems.
Fixed bug where pasting contents on IE sometimes would place the contents at the end of the editor.
Fixed so drag/drop on non IE browsers gets filtered by the paste plugin. IE doesn't have the necessary APIs.
Fixed so the paste plugin better detects Word 2007 contents not marked with -mso junk.
Fixed so image button isn't set to an active state when selecting control/media placeholder items.
Version 4.0.11 (2013-11-20)
Added the possibility to update button icon after it's been rendered.
Added new autosave_prefix option allows you to set the prefix for the local storage keys.
Added new pagebreak_split_block option to make it easier to split block elements with a page break.
Fixed bug where IE would some times produce font elements when typing out side the body root blocks.
Fixed bug where IE wouldn't properly use the configured root block element but instead use the a paragraph.
Fixed bug where IE would throw a stack overflow if control selections non images was made in inline mode.
Fixed bug where IE 8 would render an extra enter element if the contents of the editor was empty.
Fixed bug where the caret wasn't moved to the first suitable element when updating the source.
Fixed bug where protocol relative urls would be forced into http protocol.
Fixed bug where internal images with data urls such as video elements would be removed by the paste_data_images option.
Fixed bug where the autoresize plugin wouldn't properly resize the editor to initial contents some times.
Fixed bug where the templates dialog wouldn't be properly rendered on IE 7.
Fixed bug where updating styles in the advanced tab under the image dialog would remove the style attribute on cancel.
Fixed bug where tinymce.full.min.js bundle script wasn't detected when looking for the tinymce root path.
Fixed bug where the SaxParser would throw a malformed URI sequence for inproperly encoded uris.
Fixed bug where enabling table caption wouldn't properly render the caption element on IE 10 and below.
Fixed bug where the scrollbar would be placed to the left and on top of the text of menu items in RTL mode.
Fixed bug where Firefox on Mac OS X would navigate forward/backward on CMD+Arrow keys.
Fixed bug where fullscreen toggle on fixed sized editors wouldn't be properly full screened.
Fixed bug where the unlink button would remove all links from the body element in inline mode under running in IE.
Fixed bug where iOS wasn't able to place the caret inside an empty editor when clicking below the first line.
Fixed so internal document anchors in Word documents are retained when pasting using the paste from word feature.
Fixed so menu shortcuts gets rendered with the Apple command icon patch contributed by Andy Keller.
Fixed so the CSS compression of styles like "border" is a bit better for mixed values.
Fixed so the template_popup_width/template_popup_height option works properly in the template plugin.
Fixed so the languages parameter for AddOnManager.requireLangPack works the same way as for 3.x.
Fixed so the autosave plugin uses the current page path, query string and editor id as it's default prefix.
Fixed so the fullpage plugin adds/removes any link style sheets to the current iframe document.
Version 4.0.10 (2013-10-28)
Added new forced_root_block_attrs option that allows you to specify attributes for the root block.
Fixed bug where the custom resize handles didn't work properly on IE 11.
Fixed bug where the code plugin would select all contents in IE when content was updated.
Fixed bug where the scroll position wouldn't get applied to floating toolbars.
Fixed bug where focusing in/out of the editor would move the caret to the top of the editor on IE 11.
Fixed bug where the listboxes for link and image lists wasn't updated when the url/src was changed.
Fixed bug where selection bookmark elements would be visible in the elements path list.
Version 4.0.9 (2013-10-24)
Added support for external template files to template plugin just set the templates option to a URL with JSON data.
Added new allow_script_urls option. Enabled by default, trims all script urls from attributes.
Fixed bug where IE would sometimes throw a "Permission denied" error unless the Sizzle doc was properly removed.
Fixed bug where lists plugin would remove outer list items if inline editable element was within a LI parent.
Fixed bug where insert table grid widget would insert a table on item to large when using a RTL language pack.
Fixed bug where fullscreen mode wasn't rendering properly on IE 7.
Fixed bug where resize handlers wasn't moved correctly when scrolling inline editable elements.
Fixed bug where it wasn't possible to paste from Excel and possible other applications due to Clipboard API bugs in browsers.
Fixed bug where Shift+Ctrl+V didn't produce a plain text paste on IE.
Fixed bug where IE would sometimes move the selection to the a previous location.
Fixed bug where the editor wasn't properly scrolled to the content insert location in inline mode.
Fixed bug where some comments would be parsed as HTML by the SaxParser.
Fixed bug where WebKit/Blink would render tables incorrectly if unapplying formats when having multiple table cells selected.
Fixed bug where the paste_data_images option wouldn't strip all kinds of data images.
Fixed bug where the GridLayout didn't render items correctly if the contents overflowed the layout container.
Fixed bug where the Window wasn't properly positioned if the size of the button bar or title bar was wider than the contents.
Fixed bug where psuedo selectors for finding UI controls didn't work properly.
Fixed bug where resized splitbuttons would throw an exception if it didn't contain an icon.
Fixed bug where setContent would move focus into the editor even though it wasn't active.
Fixed bug where IE 11 would sometimes throw an "Invalid function" error when calling setActive on the body element.
Fixed bug where the importcss plugin would import styles from CSS files not present in the content_css array.
Fixed bug where the jQuery plugin will initialize the editors twice if the core was loaded using the script_url option.
Fixed various bugs and issues related to indentation of OL/UL list elements.
Fixed so IE 7 renders the classic mode buttons the same size as other browsers.
Fixed so document.readyState is checked when loading and initializing TinyMCE manually after page load.
Version 4.0.8 (2013-10-10)
Added RTL support so all of the UI is rendered right to left if a language pack has a _dir property set to rtl.
Fixed bug where layout managers wouldn't handle subpixel values properly. When for example the browser was zoomed in.
Fixed bug where the importcss plugin wouldn't import classes from local stylesheets with remote @import rules on Gecko.
Fixed bug where Arabic characters wouldn't be properly counted in wordcount plugin.
Fixed bug where submit event would still fire even if it was unbound on IE 10. Now the event is simply ignored.
Fixed bug where IE 11 would return border-image: none when getting style attributes with borders in them.
Fixed various UI rendering issues on older IE versions.
Fixed so readonly option renderes the editor in inline mode with all UI elements disabled and all events blocked.
Version 4.0.7 (2013-10-02)
Added new importcss_selector_filter option to importcss plugin. Makes it easier to select specific classes to import.
Added new importcss_groups option to importcss plugin. Enables you separate classes into menu groups based on filters.
Added new PastePreProcess/PastePostProcess events and reintroduced paste_preprocess/paste_postprocess paste options.
Added new paste_word_valid_elements option lets you control what elements gets pasted when pasting from Word.
Fixed so panelbutton is easier to use. It's now possible to set the panel contents to any container type.
Fixed so editor.destroy calls editor.remove so that both destroy and remove can be used to remove an editor instance.
Fixed so the searchreplace plugin doesn't move focus into the editor until you close the dialog.
Fixed so the searchreplace plugin search for next item if you hit enter inside the dialog.
Fixed so importcss_selector_converter callback is executed with the scope set to importcss plugin instance.
Fixed so the default selector converter function is exposed in importcss plugin.
Fixed issue with the tabpanel not expanding properly when the tabs where wider than the body of the panel.
Fixed issue with the menubar option producing a JS exception if set to true.
Fixed bug where closing a dialog with an opened listbox would cause errors if new dialogs where opened.
Fixed bug where hidden input elements wasn't removed when inline editor instances where removed.
Fixed bug where editors wouldn't initialize some times due to event logic not working correctly.
Fixed bug where pre elements woudl cause searchreplace and spellchecker plugins to mark incorrect locations.
Fixed bug where embed elements wouldn't be properly resized if they where configured in using the video_template_callback.
Fixed bug where paste from word would remove all BR elements since it was missing in the default paste_word_valid_elements.
Fixed bug where paste filtering wouldn't work properly on old WebKit installations pre Clipboard API.
Fixed bug where linebreaks would be removed by paste plugin on IE since it didn't properly detect Word contents.
Fixed bug where paste plugin would convert some Word paragraphs that looked like lists into lists.
Fixed bug where editors wasn't properly initialized if the document.domain is set to the same as the current domain on IE.
Fixed bug where an exception was thrown when removing an editor after opening the context menu multiple times.
Fixed bug where paste as plain text on Gecko would add extra BR elements when pasting paragraphs.
Version 4.0.6 (2013-09-12)
Added new compat3x plugin that makes it possible to load most 3.x plugins. Only available in the development package.
Added new skin_url option enables you to load local skins when using the CDN version.
Added new theme_url option enables you to load local themes when using the CDN version.
Added new importcss_file_filter option to importcss to enable users to specify what files to import from.
Added new template_preview_replace_values option to template plugin to add example data for variables.
Added image option support for addMenuItem calls. Enables you to provide a custom image for menu items.
Fixed bug where editor.insertContent wouldn't set format and selection type on events.
Fixed bug where inserting BR elements on IE 8 would thrown an exception when the range is at a empty text node.
Fixed bug where outdent of single LI element within another LI would produce an empty list element OL/UL.
Fixed bug where the bullist/numlist buttons wouldn't be deselected when deleting all contents.
Fixed bug where toggling an empty list item off wouldn't produce a new empty block element.
Fixed bug where it wasn't possible to apply lists to mixed text blocks and br lines.
Fixed bug where it wasn't possible to paste contents on iOS when the paste plugin was enabled.
Fixed bug where it wasn't possible to delete HR elements on Gecko.
Fixed bug where scrolling and refocusing using the mouse would place the caret incorrectly on IE.
Fixed bug where you needed to hit the empty paragraph to get editor focus in IE 11.
Fixed bug where activeEditor wasn't set to the correct editor when opening windows.
Fixed bug where dirty state wasn't set to false when undoing to the first undo level.
Fixed bug where pasting in inline mode on Safari on Mac wouldn't work properly.
Fixed bug where content_css wasn't loaded into the insert template dialog.
Fixed bug where setting the contents of the editor to non text contents would produce an incorrect selection range.
Fixed so code dialog height gets smaller that the viewport height if it doesn't fit.
Fixed so inline editable regions scroll when pressing enter/return.
Fixed so inline toolbar gets positioned correctly when inline element is within a scrollable container.
Fixed various memory leaks when removing editor instances dynamically.
Removed CSS for BR elements in visualblocks due to problems with Chrome and IE.
Version 4.0.5 (2013-08-27)
Added visuals for UL, LI and BR to visualblocks plugin. Patch contributed by Dan Ransom.
Added new autosave_restore_when_empty option to autosave plugin. Enabled by default.
Fixed bug where an exception was thrown when inserting images if valid_elements didn't include an ID for the image.
Fixed bug where the advlist plugin wouldn't properly render the splitbutton controls.
Fixed bug where visual blocks menu item wouldn't be marked checked when using the visualblocks_default_state option.
Fixed bug where save button in save plugin wouldn't get properly enabled when contents was changed.
Fixed bug where it was possible to insert images without any value for it's source attribute.
Fixed bug where altering image attributes wouldn't add a new undo level.
Fixed bug where import rules in CSS files wouldn't be properly imported by the importcss plugin.
Fixed bug where selectors could be imported multiple times. Producing duplicate formats.
Fixed bug where IE would throw exception if selection was changed while the editor was hidden.
Fixed so complex rules like .class:before doesn't get imported by default in the importcss plugin.
Fixed so it's possible to remove images by setting the src attribute to a blank value.
Fixed so the save_enablewhendirty setting in the save plugin is enabled by default.
Fixed so block formats drop down for classic mode can be translated properly using language packs.
Fixed so hr menu item and toolbar button gets the same translation string.
Fixed so bullet list toolbar button gets the correct translation from language packs.
Fixed issue with Chrome logging CSS warning about border styling for combo boxes.
Fixed issue with Chrome logging warnings about deprecated keyLocation property.
Fixed issue where custom_elements would not remove the some of the default rules when cloning rules from div and span.
Version 4.0.4 (2013-08-21)
Added new importcss plugin. Lets you auto import classes from CSS files similar to the 3.x behavior.
Fixed bug where resize handles would be positioned incorrectly when inline element parent was using position: relative.
Fixed bug where IE 8 would throw Unknown runtime error if the editor was placed within a P tag.
Fixed bug where removing empty lists wouldn't produce blocks or brs where the old list was in the DOM.
Fixed bug where IE 10 wouldn't properly initialize template dialog due to async loading issues.
Fixed bug where autosave wouldn't properly display the warning about content not being saved due to isDirty changes.
Fixed bug where it wouldn't be possible to type if a touchstart event was bound to the parent document.
Fixed bug where code dialog in code plugin wouldn't wouldn't add a proper undo level.
Fixed issue where resizing the editor in vertical mode would set the iframe width to a pixel value.
Fixed issue with naming of insertdatetime settings. All are now prefixed with the plugin name.
Fixed so an initial change event is fired when the user types the first character into the editor.
Fixed so swf gets mapped to object element in media plugin. Enables embedding of flash with alternative poster.
Version 4.0.3 (2013-08-08)
Added new code_dialog_width/code_dialog_height options to control code dialog size.
Added missing pastetext button that works the same way as the pastetext menu item.
Added missing smaller browse button for the classical smaller toolbars.
Fixed bug where input method would produce new lines when inserting contents to an empty editor.
Fixed bug where pasting single indented list items from Word would cause a JS exception.
Fixed bug where applying block formats inside list elements in inline mode would apply them to whole document.
Fixed bug where link editing in inline mode would cause exception on IE/WebKit.
Fixed bug where IE 10 wouldn't render the last button group properly in inline mode due to wrapping.
Fixed bug where localStorage initialization would fail on Firefox/Chrome with disabled support.
Fixed bug where image elements would get an __mce id when undo/redo:ing to a level with image changes.
Fixed bug where too long template names wouldn't fit the listbox in template plugin.
Fixed bug where alignment format options would be marked disabled when forced_root_block was set to false.
Fixed bug where UI listboxes such as fontsize, fontfamily wouldn't update properly when switching editors in inline mode.
Fixed bug where the formats select box would mark the editable container DIV as a applied format in inline mode.
Fixed bug where IE 7/8 would scroll to empty editors when initialized.
Fixed bug where IE 7/8 wouldn't display previews of format options.
Fixed bug where UI states wasn't properly updated after code was changed in the code dialog.
Fixed bug with setting contents in IE would select all contents within the editor.
Fixed so the undoManages transact function disables any other undo levels from being added while within the transaction.
Fixed so sub/sup elements gets removed when the Clear formatting action is executed.
Fixed so text/javascript type value get removed by default from script elements to match the HTML5 spec.
Version 4.0.2 (2013-07-18)
Fixed bug where formatting using menus or toolbars wasn't possible on Opera 12.15.
Fixed bug where IE 8 keyboard input would break after paste using the paste plugin.
Fixed bug where IE 8 would throw an error when populating image size in image dialog.
Fixed bug where image resizing wouldn't work properly on latest IE 10.0.9 version.
Fixed bug where focus wasn't moved to the hovered menu button in a menubar container.
Fixed bug where paste would produce an extra uneeded undo level on IE and Gecko.
Fixed so anchors gets listed in the link dialog as they where in TinyMCE 3.x.
Fixed so sub, sup and strike though gets passed through when pasting from Word.
Fixed so Ctrl+P can be used to print the current document. Patch contributed by jashua212.
Version 4.0.1 (2013-06-26)
Added new paste_as_text config option to force paste as plaintext mode.
Added new pastetext menu item that lets you toggle paste as plain text mode on/off.
Added new insertdatetime_element option to insertdatetime plugin. Enables HTML5 time element support.
Added new spellchecker_wordchar_pattern option to allow configuration of language specific characters.
Added new marker to formats menu displaying the formats used at the current selection/caret location.
Fixed bug where the position of the text color picker would be wrong if you switched to fullscreen.
Fixed bug where the link plugin would ask to add the mailto: prefix multiple times.
Fixed bug where list outdent operation could produce empty list elements on specific selections.
Fixed bug where element path wouldn't properly select parent elements on IE.
Fixed bug where IE would sometimes throw an exception when extrancting the current selection range.
Fixed bug where line feeds wasn't properly rendered in source view on IE.
Fixed bug where word count wouldn't be properly rendered on IE 7.
Fixed bug where menubuttons/listboxes would have an incorrect height on IE 7.
Fixed bug where browser spellchecking was enabled while editing inline on IE 10.
Fixed bug where spellchecker wouldn't properly find non English words.
Fixed bug where deactivating inline editor instances would force padding-top: 0 on page body.
Fixed bug where jQuery would initialize editors multiple times since it didn't check if the editor already existed.
Fixed bug where it wasn't possible to paste contents on IE 10 in modern UI mode when paste filtering was enabled.
Fixed bug where tabfocus plugin wouldn't work properly on inline editor instances.
Fixed bug where fullpage plugin would clear the existing HTML head if contents where inserted into the editor.
Fixed bug where deleting all table rows/columns in a table would cause an exception to be thrown on IE.
Fixed so color button panels gets toggled on/off when activated/deactivated.
Fixed so format menu items that can't be applied to the current selection gets disabled.
Fixed so the icon parameter for addButton isn't automatically filled if a button text is provided.
Fixed so image size fields gets updated when selecting a new image in the image dialog.
Fixed so it doesn't load any language pack if the language option is set to "en".
Fixed so ctrl+shift+z works as an alternative redo shortcut to match a common Mac OS X shortcut.
Fixed so it's not possible to drag/drop in images in Gecko by default when paste plugin is enabled.
Fixed so format menu item texts gets translated using the specified language pack.
Fixed so the image dialog title is the same as the insert/edit image button text.
Fixed so paste as plain text produces BR:s in PRE block and when forced_root_block is disabled.
Version 4.0 (2013-06-13)
Added new insertdate_dateformat, insertdate_timeformat and insertdate_formats options to insertdatetime.
Added new font_formats, fontsize_formats and block_formats options to configure fontselect, fontsizeselect and formatselect.
Added new table_clone_elements option to table plugin. Enables you to specify what elements to clone when adding columns/rows.
Added new auto detect logic for site and email urls in link plugin to match the logic found in 3.x.
Added new getParams/setParams to WindowManager to make it easier to handle params to iframe based dialogs. Contributed by Ryan Demmer.
Added new textcolor options that enables you to specify the colors you want to display. Contributed by Jennifer Arsenault.
Added new external file support for link_list and image_list options. The file format is a simple JSON file.
Added new "both" mode for the resize option. Enables resizing in both width and height.
Added new paste_data_images option that allows you to enable/disable paste of data images.
Added new fixed_toolbar_container option that allows you to add a fixed container for the inline toolbar.
Fixed so font name, font size and block format select boxes gets updated with the current format.
Fixed so the resizeTo/resizeBy methods for the theme are exposed as it as in 3.x.
Fixed so the textcolor controls are splitbuttons as in 3.x. Patch contributed by toxalot/jashua212.
Fixed bug where the theme content css wasn't loaded into the preview dialog.
Fixed bug where the template description in template dialog wouldn't display the text correctly.
Fixed bug where various UI elements wasn't properly removed when an editor instance was removed.
Fixed bug where editing links in inline mode would fail on WebKit.
Fixed bug where the pagebreak_separator option in the pagebreak plugin wasn't working properly.
Fixed bug where the child panels of the float panel in inline mode wasn't properly placed.
Fixed bug where the float panel children of windows wasn't position fixed.
Fixed bug where the size of the ok button was hardcoded, caused issues with i18n.
Fixed bug where single comment in editor would cause exceptions due to resolve path logic not detecting elements only.
Fixed bug where switching alignment of tables in dialogs wouldn't properly remove existing alignments.
Fixed bug where the table properties dialog would show columns/rows textboxes.
Fixed bug where jQuery wasn't used instead of Sizzle in the jQuery version of TinyMCE.
Fixed bug where setting resize option to false whouldn't properly render the word count.
Fixed bug where table row type change would produce multiple table section elements.
Fixed bug where table row type change on multiple rows would add them in incorrect order.
Fixed bug where fullscreen plugin would maximize the editor on resize after toggling it off.
Fixed bug where context menu would be position at an incorrect coordinate in inline mode.
Fixed bug where inserting lists in inline mode on IE would produce errors since the body would be converted.
Fixed bug where the body couldn't be styled properly in custom content_css files.
Fixed bug where template plugins menu item would override the image menu item.
Fixed bug where IE 7-8 would render the text inside inputs at the wrong vertical location.
Fixed bug where IE configured to IE 7 compatibility mode wouldn't render the icons properly.
Fixed bug where editor.focus wouldn't properly fire the focusin event on WebKit.
Fixed bug where some keyboard shortcuts wouldn't work on IE 8.
Fixed bug where the undo state wasn't updated until the end of a typing level.
Fixed bug where keyboard shortcuts on Mac OS wasn't working correctly.
Fixed bug where empty inline elements would be created when toggling formatting of in empty block.
Fixed bug where applying styles on WebKit would fail in inline mode if the user released the mouse button outside the body.
Fixed bug where the visual aids menu item wasn't selected if the editor was empty.
Fixed so the isDirty/isNotDirty states gets updated to true/false on save() and change events.
Fixed so skins have separate CSS files for inline and iframe mode.
Fixed so menus and tool tips gets constrained to the current viewport.
Fixed so an error is thrown if users load jQuery after the jQuery version of TinyMCE.
Fixed so the filetype for media dialog passes out media instead of image as file type.
Fixed so it's possible to disable the toolbar by setting it to false.
Fixed so autoresize plugin isn't initialized when the editor is in inline mode.
Fixed so the inline editing toolbar will be rendered below elements if it doesn't fit above it.
Version 4.0b3 (2013-05-15)
Added new optional advanced tab for image dialog with hspace, vspace, border and style.
Added new change event that gets fired when undo levels are added to editor instances.
Added new removed_menuitems option enables you to list menu items to remove from menus.
Added new external_plugins option enables you to specify external locations for plugins.
Added new language_url option enables you to specify an external location for the language pack.
Added new table toolbar control that displays a menu for inserting/editing menus.
Fixed bug where IE 10 wouldn't load files properly from cache.
Fixed bug where image dialog wouldn't properly remove width/height if blanked.
Fixed bug where all events wasn't properly unbound when editor instances where removed.
Fixed bug where data- attributes wasn't working properly in the SaxParser.
Fixed bug where Gecko wouldn't properly render broken images.
Fixed bug where Gecko wouldn't produce the same error dialog on paste as other browsers.
Fixed bug where is wasn't possible to prevent execCommands in beforeExecCommand event.
Fixed bug where the fullpage_hide_in_source_view option wasn't working in the fullpage plugin.
Fixed bug where the WindowManager close method wouldn't properly close the top most window.
Fixed bug where it wasn't possible to paste in IE 10 due to JS exception.
Fixed bug where tab key didn't move to the right child control in tabpanels.
Fixed bug where enter inside a form would focus the first button like control in TinyMCE.
Fixed bug where it would match scripts that looked like the tinymce base directory incorrectly.
Fixed bug where the spellchecker wouldn't properly toggle off the spellcheck mode if no errors where found.
Fixed bug in searchreplace plugin where it would remove all spans instead of the marker spans.
Fixed issue where selector wouldn't disable existing mode setting.
Fixed so it's easier to configure the menu and menubar.
Fixed so bodyId/bodyClass is applied to preview as it's done to the editor iframe.
Version 4.0b2 (2013-04-24)
Added new rel_list option to link plugin. Enables you to specify values for a rel drop down.
Added new target_list option to link plugin. Enables you to add to or disable the link targets.
Added new link_list option to link plugin. Enables you to specify a list of links to pick from.
Added new image_list option to image pluigin. Enables you to specify a list of images to pick from.
Added new textcolor plugin. This plugin holds the text color and text background color buttons.
Fixed bug where alignment of images wasn't working properly on Firefox.
Fixed bug where IE 8 would throw error when inserting a table.
Fixed bug where IE 8 wouldn't render the element path properly.
Fixed bug where old IE versions would render a red focus border.
Fixed bug where old IE versions would render a frameborder for iframes.
Fixed bug where WebKit wouldn't properly open the cell properties dialog on edge case selection.
Fixed bug where charmap wouldn't correctly render all characters in grid.
Fixed bug where link dialog wouldn't update the link text properly.
Fixed bug where the focus/blur states on inline editors wasn't handled correctly on IE.
Fixed bug where IE would throw "unknown error" exception sometimes in ForceBlocks logic.
Fixed bug where IE would't properly render disabled buttons in button groups.
Fixed bug where tab key wouldn't properly move to next input field in dialogs.
Fixed bug where resize handles for tables and images would appear at wrong positions on IE 8.
Fixed bug where dialogs would produce stack overflow if title was wider than content.
Fixed bug with table cell/row menu items being enabled even if no cell was selected.
Fixed so the text to display is after the URL field in the link dialog.
Fixed so the width setting applies to the editor panel in modern theme.
Fixed so it's easier to make custom icons for buttons using plain old images.
Version 4.0b1 (2013-04-11)
Added new node.js based build process used uglify, amdlc, jake etc.
Added new package.json to enable easy installation of dependent npm packages used for building.
Added new link, image, charmap, anchor, code, hr plugins since these are now moved out of the theme.
Rewrote all plugins and themes from scratch so they match the new UI framework.
Replaced all events to use the more common <target>.on/off(<event>) methods instead of <target>.<event>.add/remove.
Rewrote the TinyMCE core to use AMD style modules. Gets compiled to an inline library using amdlc.
Rewrote all core logic to pass jshint rules. Each file has specific jshint rules.
Removed all IE6 specific logic since 4.x will no longer support such an old browser.
Reworked the file names and directory structure of the whole project to be more similar to other JS projects.
Replaced tinymce.util.Cookie with tinymce.util.LocalStorage. Fallback to userData for IE 7 native localStorage for the rest.
Replaced the old 3.x UI with a new modern UI framework.
Removed "simple" theme and added new "modern" theme.
Removed advhr, advimage, advlink, iespell, inlinepopups, xhtmlxtras and style plugins.
Updated Sizzle to the latest version.

View File

@ -0,0 +1 @@
!function(a){function b(){function b(a){"remove"===a&&this.each(function(a,b){var c=e(b);c&&c.remove()}),this.find("span.mceEditor,div.mceEditor").each(function(a,b){var c=tinymce.get(b.id.replace(/_parent$/,""));c&&c.remove()})}function d(a){var c,d=this;if(null!=a)b.call(d),d.each(function(b,c){var d;(d=tinymce.get(c.id))&&d.setContent(a)});else if(d.length>0&&(c=tinymce.get(d[0].id)))return c.getContent()}function e(a){var b=null;return a&&a.id&&f.tinymce&&(b=tinymce.get(a.id)),b}function g(a){return!!(a&&a.length&&f.tinymce&&a.is(":tinymce"))}var h={};a.each(["text","html","val"],function(b,f){var i=h[f]=a.fn[f],j="text"===f;a.fn[f]=function(b){var f=this;if(!g(f))return i.apply(f,arguments);if(b!==c)return d.call(f.filter(":tinymce"),b),i.apply(f.not(":tinymce"),arguments),f;var h="",k=arguments;return(j?f:f.eq(0)).each(function(b,c){var d=e(c);h+=d?j?d.getContent().replace(/<(?:"[^"]*"|'[^']*'|[^'">])*>/g,""):d.getContent({save:!0}):i.apply(a(c),k)}),h}}),a.each(["append","prepend"],function(b,d){var f=h[d]=a.fn[d],i="prepend"===d;a.fn[d]=function(a){var b=this;return g(b)?a!==c?("string"==typeof a&&b.filter(":tinymce").each(function(b,c){var d=e(c);d&&d.setContent(i?a+d.getContent():d.getContent()+a)}),f.apply(b.not(":tinymce"),arguments),b):void 0:f.apply(b,arguments)}}),a.each(["remove","replaceWith","replaceAll","empty"],function(c,d){var e=h[d]=a.fn[d];a.fn[d]=function(){return b.call(this,d),e.apply(this,arguments)}}),h.attr=a.fn.attr,a.fn.attr=function(b,f){var i=this,j=arguments;if(!b||"value"!==b||!g(i))return f!==c?h.attr.apply(i,j):h.attr.apply(i,j);if(f!==c)return d.call(i.filter(":tinymce"),f),h.attr.apply(i.not(":tinymce"),j),i;var k=i[0],l=e(k);return l?l.getContent({save:!0}):h.attr.apply(a(k),j)}}var c,d,e=[],f=window;a.fn.tinymce=function(c){function g(){var d=[],e=0;k||(b(),k=!0),l.each(function(a,b){var f,g=b.id,h=c.oninit;g||(b.id=g=tinymce.DOM.uniqueId()),tinymce.get(g)||(f=new tinymce.Editor(g,c,tinymce.EditorManager),d.push(f),f.on("init",function(){var a,b=h;l.css("visibility",""),h&&++e==d.length&&("string"==typeof b&&(a=-1===b.indexOf(".")?null:tinymce.resolve(b.replace(/\.\w+$/,"")),b=tinymce.resolve(b)),b.apply(a||tinymce,d))}))}),a.each(d,function(a,b){b.render()})}var h,i,j,k,l=this,m="";if(!l.length)return l;if(!c)return window.tinymce?tinymce.get(l[0].id):null;if(l.css("visibility","hidden"),f.tinymce||d||!(h=c.script_url))1===d?e.push(g):g();else{d=1,i=h.substring(0,h.lastIndexOf("/")),-1!=h.indexOf(".min")&&(m=".min"),f.tinymce=f.tinyMCEPreInit||{base:i,suffix:m},-1!=h.indexOf("gzip")&&(j=c.language||"en",h=h+(/\?/.test(h)?"&":"?")+"js=true&core=true&suffix="+escape(m)+"&themes="+escape(c.theme||"modern")+"&plugins="+escape(c.plugins||"")+"&languages="+(j||""),f.tinyMCE_GZ||(f.tinyMCE_GZ={start:function(){function b(a){tinymce.ScriptLoader.markDone(tinymce.baseURI.toAbsolute(a))}b("langs/"+j+".js"),b("themes/"+c.theme+"/theme"+m+".js"),b("themes/"+c.theme+"/langs/"+j+".js"),a.each(c.plugins.split(","),function(a,c){c&&(b("plugins/"+c+"/plugin"+m+".js"),b("plugins/"+c+"/langs/"+j+".js"))})},end:function(){}}));var n=document.createElement("script");n.type="text/javascript",n.onload=n.onreadystatechange=function(b){b=b||window.event,2===d||"load"!=b.type&&!/complete|loaded/.test(n.readyState)||(tinymce.dom.Event.domLoaded=1,d=2,c.script_loaded&&c.script_loaded(),g(),a.each(e,function(a,b){b()}))},n.src=h,document.body.appendChild(n)}return l},a.extend(a.expr[":"],{tinymce:function(a){var b;return a.id&&"tinymce"in window&&(b=tinymce.get(a.id),b&&b.editorManager===tinymce)?!0:!1}})}(jQuery);

View File

@ -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.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

View File

@ -0,0 +1,97 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('advlist', function(editor) {
var olMenuItems, ulMenuItems, lastStyles = {};
function buildMenuItems(listName, styleValues) {
var items = [];
tinymce.each(styleValues.split(/[ ,]/), function(styleValue) {
items.push({
text: styleValue.replace(/\-/g, ' ').replace(/\b\w/g, function(chr) {
return chr.toUpperCase();
}),
data: styleValue == 'default' ? '' : styleValue
});
});
return items;
}
olMenuItems = buildMenuItems('OL', editor.getParam(
"advlist_number_styles",
"default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman"
));
ulMenuItems = buildMenuItems('UL', editor.getParam("advlist_bullet_styles", "default,circle,disc,square"));
function applyListFormat(listName, styleValue) {
editor.undoManager.transact(function() {
var list, dom = editor.dom, sel = editor.selection;
// Check for existing list element
list = dom.getParent(sel.getNode(), 'ol,ul');
// Switch/add list type if needed
if (!list || list.nodeName != listName || styleValue === false) {
editor.execCommand(listName == 'UL' ? 'InsertUnorderedList' : 'InsertOrderedList');
}
// Set style
styleValue = styleValue === false ? lastStyles[listName] : styleValue;
lastStyles[listName] = styleValue;
list = dom.getParent(sel.getNode(), 'ol,ul');
if (list) {
dom.setStyle(list, 'listStyleType', styleValue ? styleValue : null);
list.removeAttribute('data-mce-style');
}
editor.focus();
});
}
function updateSelection(e) {
var listStyleType = editor.dom.getStyle(editor.dom.getParent(editor.selection.getNode(), 'ol,ul'), 'listStyleType') || '';
e.control.items().each(function(ctrl) {
ctrl.active(ctrl.settings.data === listStyleType);
});
}
editor.addButton('numlist', {
type: 'splitbutton',
tooltip: 'Numbered list',
menu: olMenuItems,
onshow: updateSelection,
onselect: function(e) {
applyListFormat('OL', e.control.settings.data);
},
onclick: function() {
applyListFormat('OL', false);
}
});
editor.addButton('bullist', {
type: 'splitbutton',
tooltip: 'Bullet list',
menu: ulMenuItems,
onshow: updateSelection,
onselect: function(e) {
applyListFormat('UL', e.control.settings.data);
},
onclick: function() {
applyListFormat('UL', false);
}
});
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("advlist",function(a){function b(a,b){var c=[];return tinymce.each(b.split(/[ ,]/),function(a){c.push({text:a.replace(/\-/g," ").replace(/\b\w/g,function(a){return a.toUpperCase()}),data:"default"==a?"":a})}),c}function c(b,c){a.undoManager.transact(function(){var d,e=a.dom,f=a.selection;d=e.getParent(f.getNode(),"ol,ul"),d&&d.nodeName==b&&c!==!1||a.execCommand("UL"==b?"InsertUnorderedList":"InsertOrderedList"),c=c===!1?g[b]:c,g[b]=c,d=e.getParent(f.getNode(),"ol,ul"),d&&(e.setStyle(d,"listStyleType",c?c:null),d.removeAttribute("data-mce-style")),a.focus()})}function d(b){var c=a.dom.getStyle(a.dom.getParent(a.selection.getNode(),"ol,ul"),"listStyleType")||"";b.control.items().each(function(a){a.active(a.settings.data===c)})}var e,f,g={};e=b("OL",a.getParam("advlist_number_styles","default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman")),f=b("UL",a.getParam("advlist_bullet_styles","default,circle,disc,square")),a.addButton("numlist",{type:"splitbutton",tooltip:"Numbered list",menu:e,onshow:d,onselect:function(a){c("OL",a.control.settings.data)},onclick:function(){c("OL",!1)}}),a.addButton("bullist",{type:"splitbutton",tooltip:"Bullet list",menu:f,onshow:d,onselect:function(a){c("UL",a.control.settings.data)},onclick:function(){c("UL",!1)}})});

View File

@ -0,0 +1,45 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('anchor', function(editor) {
function showDialog() {
var selectedNode = editor.selection.getNode(), name = '';
if (selectedNode.tagName == 'A') {
name = selectedNode.name || selectedNode.id || '';
}
editor.windowManager.open({
title: 'Anchor',
body: {type: 'textbox', name: 'name', size: 40, label: 'Name', value: name},
onsubmit: function(e) {
editor.execCommand('mceInsertContent', false, editor.dom.createHTML('a', {
id: e.data.name
}));
}
});
}
editor.addButton('anchor', {
icon: 'anchor',
tooltip: 'Anchor',
onclick: showDialog,
stateSelector: 'a:not([href])'
});
editor.addMenuItem('anchor', {
icon: 'anchor',
text: 'Anchor',
context: 'insert',
onclick: showDialog
});
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("anchor",function(a){function b(){var b=a.selection.getNode(),c="";"A"==b.tagName&&(c=b.name||b.id||""),a.windowManager.open({title:"Anchor",body:{type:"textbox",name:"name",size:40,label:"Name",value:c},onsubmit:function(b){a.execCommand("mceInsertContent",!1,a.dom.createHTML("a",{id:b.data.name}))}})}a.addButton("anchor",{icon:"anchor",tooltip:"Anchor",onclick:b,stateSelector:"a:not([href])"}),a.addMenuItem("anchor",{icon:"anchor",text:"Anchor",context:"insert",onclick:b})});

View File

@ -0,0 +1,194 @@
/**
* plugin.js
*
* Copyright 2011, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('autolink', function(editor) {
var AutoUrlDetectState;
editor.on("keydown", function(e) {
if (e.keyCode == 13) {
return handleEnter(editor);
}
});
// Internet Explorer has built-in automatic linking for most cases
if (tinymce.Env.ie) {
editor.on("focus", function() {
if (!AutoUrlDetectState) {
AutoUrlDetectState = true;
try {
editor.execCommand('AutoUrlDetect', false, true);
} catch (ex) {
// Ignore
}
}
});
return;
}
editor.on("keypress", function(e) {
if (e.keyCode == 41) {
return handleEclipse(editor);
}
});
editor.on("keyup", function(e) {
if (e.keyCode == 32) {
return handleSpacebar(editor);
}
});
function handleEclipse(editor) {
parseCurrentLine(editor, -1, '(', true);
}
function handleSpacebar(editor) {
parseCurrentLine(editor, 0, '', true);
}
function handleEnter(editor) {
parseCurrentLine(editor, -1, '', false);
}
function parseCurrentLine(editor, end_offset, delimiter) {
var rng, end, start, endContainer, bookmark, text, matches, prev, len, rngText;
function scopeIndex(container, index) {
if (index < 0) {
index = 0;
}
if (container.nodeType == 3) {
var len = container.data.length;
if (index > len) {
index = len;
}
}
return index;
}
function setStart(container, offset) {
if (container.nodeType != 1 || container.hasChildNodes()) {
rng.setStart(container, scopeIndex(container, offset));
} else {
rng.setStartBefore(container);
}
}
function setEnd(container, offset) {
if (container.nodeType != 1 || container.hasChildNodes()) {
rng.setEnd(container, scopeIndex(container, offset));
} else {
rng.setEndAfter(container);
}
}
// We need at least five characters to form a URL,
// hence, at minimum, five characters from the beginning of the line.
rng = editor.selection.getRng(true).cloneRange();
if (rng.startOffset < 5) {
// During testing, the caret is placed inbetween two text nodes.
// The previous text node contains the URL.
prev = rng.endContainer.previousSibling;
if (!prev) {
if (!rng.endContainer.firstChild || !rng.endContainer.firstChild.nextSibling) {
return;
}
prev = rng.endContainer.firstChild.nextSibling;
}
len = prev.length;
setStart(prev, len);
setEnd(prev, len);
if (rng.endOffset < 5) {
return;
}
end = rng.endOffset;
endContainer = prev;
} else {
endContainer = rng.endContainer;
// Get a text node
if (endContainer.nodeType != 3 && endContainer.firstChild) {
while (endContainer.nodeType != 3 && endContainer.firstChild) {
endContainer = endContainer.firstChild;
}
// Move range to text node
if (endContainer.nodeType == 3) {
setStart(endContainer, 0);
setEnd(endContainer, endContainer.nodeValue.length);
}
}
if (rng.endOffset == 1) {
end = 2;
} else {
end = rng.endOffset - 1 - end_offset;
}
}
start = end;
do {
// Move the selection one character backwards.
setStart(endContainer, end >= 2 ? end - 2 : 0);
setEnd(endContainer, end >= 1 ? end - 1 : 0);
end -= 1;
rngText = rng.toString();
// Loop until one of the following is found: a blank space, &nbsp;, delimiter, (end-2) >= 0
} while (rngText != ' ' && rngText !== '' && rngText.charCodeAt(0) != 160 && (end - 2) >= 0 && rngText != delimiter);
if (rng.toString() == delimiter || rng.toString().charCodeAt(0) == 160) {
setStart(endContainer, end);
setEnd(endContainer, start);
end += 1;
} else if (rng.startOffset === 0) {
setStart(endContainer, 0);
setEnd(endContainer, start);
} else {
setStart(endContainer, end);
setEnd(endContainer, start);
}
// Exclude last . from word like "www.site.com."
text = rng.toString();
if (text.charAt(text.length - 1) == '.') {
setEnd(endContainer, start - 1);
}
text = rng.toString();
matches = text.match(/^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|(?:mailto:)?[A-Z0-9._%+\-]+@)(.+)$/i);
if (matches) {
if (matches[1] == 'www.') {
matches[1] = 'http://www.';
} else if (/@$/.test(matches[1]) && !/^mailto:/.test(matches[1])) {
matches[1] = 'mailto:' + matches[1];
}
bookmark = editor.selection.getBookmark();
editor.selection.setRng(rng);
editor.execCommand('createlink', false, matches[1] + matches[2]);
editor.selection.moveToBookmark(bookmark);
editor.nodeChanged();
}
}
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("autolink",function(a){function b(a){e(a,-1,"(",!0)}function c(a){e(a,0,"",!0)}function d(a){e(a,-1,"",!1)}function e(a,b,c){function d(a,b){if(0>b&&(b=0),3==a.nodeType){var c=a.data.length;b>c&&(b=c)}return b}function e(a,b){1!=a.nodeType||a.hasChildNodes()?g.setStart(a,d(a,b)):g.setStartBefore(a)}function f(a,b){1!=a.nodeType||a.hasChildNodes()?g.setEnd(a,d(a,b)):g.setEndAfter(a)}var g,h,i,j,k,l,m,n,o,p;if(g=a.selection.getRng(!0).cloneRange(),g.startOffset<5){if(n=g.endContainer.previousSibling,!n){if(!g.endContainer.firstChild||!g.endContainer.firstChild.nextSibling)return;n=g.endContainer.firstChild.nextSibling}if(o=n.length,e(n,o),f(n,o),g.endOffset<5)return;h=g.endOffset,j=n}else{if(j=g.endContainer,3!=j.nodeType&&j.firstChild){for(;3!=j.nodeType&&j.firstChild;)j=j.firstChild;3==j.nodeType&&(e(j,0),f(j,j.nodeValue.length))}h=1==g.endOffset?2:g.endOffset-1-b}i=h;do e(j,h>=2?h-2:0),f(j,h>=1?h-1:0),h-=1,p=g.toString();while(" "!=p&&""!==p&&160!=p.charCodeAt(0)&&h-2>=0&&p!=c);g.toString()==c||160==g.toString().charCodeAt(0)?(e(j,h),f(j,i),h+=1):0===g.startOffset?(e(j,0),f(j,i)):(e(j,h),f(j,i)),l=g.toString(),"."==l.charAt(l.length-1)&&f(j,i-1),l=g.toString(),m=l.match(/^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|(?:mailto:)?[A-Z0-9._%+\-]+@)(.+)$/i),m&&("www."==m[1]?m[1]="http://www.":/@$/.test(m[1])&&!/^mailto:/.test(m[1])&&(m[1]="mailto:"+m[1]),k=a.selection.getBookmark(),a.selection.setRng(g),a.execCommand("createlink",!1,m[1]+m[2]),a.selection.moveToBookmark(k),a.nodeChanged())}var f;return a.on("keydown",function(b){return 13==b.keyCode?d(a):void 0}),tinymce.Env.ie?void a.on("focus",function(){if(!f){f=!0;try{a.execCommand("AutoUrlDetect",!1,!0)}catch(b){}}}):(a.on("keypress",function(c){return 41==c.keyCode?b(a):void 0}),void a.on("keyup",function(b){return 32==b.keyCode?c(a):void 0}))});

View File

@ -0,0 +1,152 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
/*eslint no-nested-ternary:0 */
/**
* Auto Resize
*
* This plugin automatically resizes the content area to fit its content height.
* It will retain a minimum height, which is the height of the content area when
* it's initialized.
*/
tinymce.PluginManager.add('autoresize', function(editor) {
var settings = editor.settings, oldSize = 0;
function isFullscreen() {
return editor.plugins.fullscreen && editor.plugins.fullscreen.isFullscreen();
}
if (editor.settings.inline) {
return;
}
/**
* This method gets executed each time the editor needs to resize.
*/
function resize(e) {
var deltaSize, doc, body, docElm, DOM = tinymce.DOM, resizeHeight, myHeight,
marginTop, marginBottom, paddingTop, paddingBottom, borderTop, borderBottom;
doc = editor.getDoc();
if (!doc) {
return;
}
body = doc.body;
docElm = doc.documentElement;
resizeHeight = settings.autoresize_min_height;
if (!body || (e && e.type === "setcontent" && e.initial) || isFullscreen()) {
if (body && docElm) {
body.style.overflowY = "auto";
docElm.style.overflowY = "auto"; // Old IE
}
return;
}
// Calculate outer height of the body element using CSS styles
marginTop = editor.dom.getStyle(body, 'margin-top', true);
marginBottom = editor.dom.getStyle(body, 'margin-bottom', true);
paddingTop = editor.dom.getStyle(body, 'padding-top', true);
paddingBottom = editor.dom.getStyle(body, 'padding-bottom', true);
borderTop = editor.dom.getStyle(body, 'border-top-width', true);
borderBottom = editor.dom.getStyle(body, 'border-bottom-width', true);
myHeight = body.offsetHeight + parseInt(marginTop, 10) + parseInt(marginBottom, 10) +
parseInt(paddingTop, 10) + parseInt(paddingBottom, 10) +
parseInt(borderTop, 10) + parseInt(borderBottom, 10);
// Make sure we have a valid height
if (isNaN(myHeight) || myHeight <= 0) {
// Get height differently depending on the browser used
myHeight = tinymce.Env.ie ? body.scrollHeight : (tinymce.Env.webkit && body.clientHeight === 0 ? 0 : body.offsetHeight);
}
// Don't make it smaller than the minimum height
if (myHeight > settings.autoresize_min_height) {
resizeHeight = myHeight;
}
// If a maximum height has been defined don't exceed this height
if (settings.autoresize_max_height && myHeight > settings.autoresize_max_height) {
resizeHeight = settings.autoresize_max_height;
body.style.overflowY = "auto";
docElm.style.overflowY = "auto"; // Old IE
} else {
body.style.overflowY = "hidden";
docElm.style.overflowY = "hidden"; // Old IE
body.scrollTop = 0;
}
// Resize content element
if (resizeHeight !== oldSize) {
deltaSize = resizeHeight - oldSize;
DOM.setStyle(editor.iframeElement, 'height', resizeHeight + 'px');
oldSize = resizeHeight;
// WebKit doesn't decrease the size of the body element until the iframe gets resized
// So we need to continue to resize the iframe down until the size gets fixed
if (tinymce.isWebKit && deltaSize < 0) {
resize(e);
}
}
}
/**
* Calls the resize x times in 100ms intervals. We can't wait for load events since
* the CSS files might load async.
*/
function wait(times, interval, callback) {
setTimeout(function() {
resize({});
if (times--) {
wait(times, interval, callback);
} else if (callback) {
callback();
}
}, interval);
}
// Define minimum height
settings.autoresize_min_height = parseInt(editor.getParam('autoresize_min_height', editor.getElement().offsetHeight), 10);
// Define maximum height
settings.autoresize_max_height = parseInt(editor.getParam('autoresize_max_height', 0), 10);
// Add padding at the bottom for better UX
editor.on("init", function() {
var overflowPadding = editor.getParam('autoresize_overflow_padding', 1);
editor.dom.setStyles(editor.getBody(), {
paddingBottom: editor.getParam('autoresize_bottom_margin', 50),
paddingLeft: overflowPadding,
paddingRight: overflowPadding
});
});
// Add appropriate listeners for resizing content area
editor.on("nodechange setcontent keyup FullscreenStateChanged", resize);
if (editor.getParam('autoresize_on_init', true)) {
editor.on('init', function() {
// Hit it 20 times in 100 ms intervals
wait(20, 100, function() {
// Hit it 5 times in 1 sec intervals
wait(5, 1000);
});
});
}
// Register the command so that it can be invoked by using tinyMCE.activeEditor.execCommand('mceExample');
editor.addCommand('mceAutoResize', resize);
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("autoresize",function(a){function b(){return a.plugins.fullscreen&&a.plugins.fullscreen.isFullscreen()}function c(d){var g,h,i,j,k,l,m,n,o,p,q,r,s=tinymce.DOM;if(h=a.getDoc()){if(i=h.body,j=h.documentElement,k=e.autoresize_min_height,!i||d&&"setcontent"===d.type&&d.initial||b())return void(i&&j&&(i.style.overflowY="auto",j.style.overflowY="auto"));m=a.dom.getStyle(i,"margin-top",!0),n=a.dom.getStyle(i,"margin-bottom",!0),o=a.dom.getStyle(i,"padding-top",!0),p=a.dom.getStyle(i,"padding-bottom",!0),q=a.dom.getStyle(i,"border-top-width",!0),r=a.dom.getStyle(i,"border-bottom-width",!0),l=i.offsetHeight+parseInt(m,10)+parseInt(n,10)+parseInt(o,10)+parseInt(p,10)+parseInt(q,10)+parseInt(r,10),(isNaN(l)||0>=l)&&(l=tinymce.Env.ie?i.scrollHeight:tinymce.Env.webkit&&0===i.clientHeight?0:i.offsetHeight),l>e.autoresize_min_height&&(k=l),e.autoresize_max_height&&l>e.autoresize_max_height?(k=e.autoresize_max_height,i.style.overflowY="auto",j.style.overflowY="auto"):(i.style.overflowY="hidden",j.style.overflowY="hidden",i.scrollTop=0),k!==f&&(g=k-f,s.setStyle(a.iframeElement,"height",k+"px"),f=k,tinymce.isWebKit&&0>g&&c(d))}}function d(a,b,e){setTimeout(function(){c({}),a--?d(a,b,e):e&&e()},b)}var e=a.settings,f=0;a.settings.inline||(e.autoresize_min_height=parseInt(a.getParam("autoresize_min_height",a.getElement().offsetHeight),10),e.autoresize_max_height=parseInt(a.getParam("autoresize_max_height",0),10),a.on("init",function(){var b=a.getParam("autoresize_overflow_padding",1);a.dom.setStyles(a.getBody(),{paddingBottom:a.getParam("autoresize_bottom_margin",50),paddingLeft:b,paddingRight:b})}),a.on("nodechange setcontent keyup FullscreenStateChanged",c),a.getParam("autoresize_on_init",!0)&&a.on("init",function(){d(20,100,function(){d(5,1e3)})}),a.addCommand("mceAutoResize",c))});

View File

@ -0,0 +1,165 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
// Internal unload handler will be called before the page is unloaded
// Needs to be outside the plugin since it would otherwise keep
// a reference to editor in closue scope
/*eslint no-func-assign:0 */
tinymce._beforeUnloadHandler = function() {
var msg;
tinymce.each(tinymce.editors, function(editor) {
// Store a draft for each editor instance
if (editor.plugins.autosave) {
editor.plugins.autosave.storeDraft();
}
// Setup a return message if the editor is dirty
if (!msg && editor.isDirty() && editor.getParam("autosave_ask_before_unload", true)) {
msg = editor.translate("You have unsaved changes are you sure you want to navigate away?");
}
});
return msg;
};
tinymce.PluginManager.add('autosave', function(editor) {
var settings = editor.settings, LocalStorage = tinymce.util.LocalStorage, prefix, started;
prefix = settings.autosave_prefix || 'tinymce-autosave-{path}{query}-{id}-';
prefix = prefix.replace(/\{path\}/g, document.location.pathname);
prefix = prefix.replace(/\{query\}/g, document.location.search);
prefix = prefix.replace(/\{id\}/g, editor.id);
function parseTime(time, defaultTime) {
var multipels = {
s: 1000,
m: 60000
};
time = /^(\d+)([ms]?)$/.exec('' + (time || defaultTime));
return (time[2] ? multipels[time[2]] : 1) * parseInt(time, 10);
}
function hasDraft() {
var time = parseInt(LocalStorage.getItem(prefix + "time"), 10) || 0;
if (new Date().getTime() - time > settings.autosave_retention) {
removeDraft(false);
return false;
}
return true;
}
function removeDraft(fire) {
LocalStorage.removeItem(prefix + "draft");
LocalStorage.removeItem(prefix + "time");
if (fire !== false) {
editor.fire('RemoveDraft');
}
}
function storeDraft() {
if (!isEmpty() && editor.isDirty()) {
LocalStorage.setItem(prefix + "draft", editor.getContent({format: 'raw', no_events: true}));
LocalStorage.setItem(prefix + "time", new Date().getTime());
editor.fire('StoreDraft');
}
}
function restoreDraft() {
if (hasDraft()) {
editor.setContent(LocalStorage.getItem(prefix + "draft"), {format: 'raw'});
editor.fire('RestoreDraft');
}
}
function startStoreDraft() {
if (!started) {
setInterval(function() {
if (!editor.removed) {
storeDraft();
}
}, settings.autosave_interval);
started = true;
}
}
settings.autosave_interval = parseTime(settings.autosave_interval, '30s');
settings.autosave_retention = parseTime(settings.autosave_retention, '20m');
function postRender() {
var self = this;
self.disabled(!hasDraft());
editor.on('StoreDraft RestoreDraft RemoveDraft', function() {
self.disabled(!hasDraft());
});
startStoreDraft();
}
function restoreLastDraft() {
editor.undoManager.beforeChange();
restoreDraft();
removeDraft();
editor.undoManager.add();
}
editor.addButton('restoredraft', {
title: 'Restore last draft',
onclick: restoreLastDraft,
onPostRender: postRender
});
editor.addMenuItem('restoredraft', {
text: 'Restore last draft',
onclick: restoreLastDraft,
onPostRender: postRender,
context: 'file'
});
function isEmpty(html) {
var forcedRootBlockName = editor.settings.forced_root_block;
html = tinymce.trim(typeof(html) == "undefined" ? editor.getBody().innerHTML : html);
return html === '' || new RegExp(
'^<' + forcedRootBlockName + '[^>]*>((\u00a0|&nbsp;|[ \t]|<br[^>]*>)+?|)<\/' + forcedRootBlockName + '>|<br>$', 'i'
).test(html);
}
if (editor.settings.autosave_restore_when_empty !== false) {
editor.on('init', function() {
if (hasDraft() && isEmpty()) {
restoreDraft();
}
});
editor.on('saveContent', function() {
removeDraft();
});
}
window.onbeforeunload = tinymce._beforeUnloadHandler;
this.hasDraft = hasDraft;
this.storeDraft = storeDraft;
this.restoreDraft = restoreDraft;
this.removeDraft = removeDraft;
this.isEmpty = isEmpty;
});

View File

@ -0,0 +1 @@
tinymce._beforeUnloadHandler=function(){var a;return tinymce.each(tinymce.editors,function(b){b.plugins.autosave&&b.plugins.autosave.storeDraft(),!a&&b.isDirty()&&b.getParam("autosave_ask_before_unload",!0)&&(a=b.translate("You have unsaved changes are you sure you want to navigate away?"))}),a},tinymce.PluginManager.add("autosave",function(a){function b(a,b){var c={s:1e3,m:6e4};return a=/^(\d+)([ms]?)$/.exec(""+(a||b)),(a[2]?c[a[2]]:1)*parseInt(a,10)}function c(){var a=parseInt(n.getItem(k+"time"),10)||0;return(new Date).getTime()-a>m.autosave_retention?(d(!1),!1):!0}function d(b){n.removeItem(k+"draft"),n.removeItem(k+"time"),b!==!1&&a.fire("RemoveDraft")}function e(){!j()&&a.isDirty()&&(n.setItem(k+"draft",a.getContent({format:"raw",no_events:!0})),n.setItem(k+"time",(new Date).getTime()),a.fire("StoreDraft"))}function f(){c()&&(a.setContent(n.getItem(k+"draft"),{format:"raw"}),a.fire("RestoreDraft"))}function g(){l||(setInterval(function(){a.removed||e()},m.autosave_interval),l=!0)}function h(){var b=this;b.disabled(!c()),a.on("StoreDraft RestoreDraft RemoveDraft",function(){b.disabled(!c())}),g()}function i(){a.undoManager.beforeChange(),f(),d(),a.undoManager.add()}function j(b){var c=a.settings.forced_root_block;return b=tinymce.trim("undefined"==typeof b?a.getBody().innerHTML:b),""===b||new RegExp("^<"+c+"[^>]*>((\xa0|&nbsp;|[ ]|<br[^>]*>)+?|)</"+c+">|<br>$","i").test(b)}var k,l,m=a.settings,n=tinymce.util.LocalStorage;k=m.autosave_prefix||"tinymce-autosave-{path}{query}-{id}-",k=k.replace(/\{path\}/g,document.location.pathname),k=k.replace(/\{query\}/g,document.location.search),k=k.replace(/\{id\}/g,a.id),m.autosave_interval=b(m.autosave_interval,"30s"),m.autosave_retention=b(m.autosave_retention,"20m"),a.addButton("restoredraft",{title:"Restore last draft",onclick:i,onPostRender:h}),a.addMenuItem("restoredraft",{text:"Restore last draft",onclick:i,onPostRender:h,context:"file"}),a.settings.autosave_restore_when_empty!==!1&&(a.on("init",function(){c()&&j()&&f()}),a.on("saveContent",function(){d()})),window.onbeforeunload=tinymce._beforeUnloadHandler,this.hasDraft=c,this.storeDraft=e,this.restoreDraft=f,this.removeDraft=d,this.isEmpty=j});

View File

@ -0,0 +1,123 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
(function() {
tinymce.create('tinymce.plugins.BBCodePlugin', {
init : function(ed) {
var self = this, dialect = ed.getParam('bbcode_dialect', 'punbb').toLowerCase();
ed.on('beforeSetContent', function(e) {
e.content = self['_' + dialect + '_bbcode2html'](e.content);
});
ed.on('postProcess', function(e) {
if (e.set) {
e.content = self['_' + dialect + '_bbcode2html'](e.content);
}
if (e.get) {
e.content = self['_' + dialect + '_html2bbcode'](e.content);
}
});
},
getInfo: function() {
return {
longname: 'BBCode Plugin',
author: 'Moxiecode Systems AB',
authorurl: 'http://www.tinymce.com',
infourl: 'http://www.tinymce.com/wiki.php/Plugin:bbcode'
};
},
// Private methods
// HTML -> BBCode in PunBB dialect
_punbb_html2bbcode : function(s) {
s = tinymce.trim(s);
function rep(re, str) {
s = s.replace(re, str);
}
// example: <strong> to [b]
rep(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi, "[url=$1]$2[/url]");
rep(/<font.*?color=\"(.*?)\".*?class=\"codeStyle\".*?>(.*?)<\/font>/gi, "[code][color=$1]$2[/color][/code]");
rep(/<font.*?color=\"(.*?)\".*?class=\"quoteStyle\".*?>(.*?)<\/font>/gi, "[quote][color=$1]$2[/color][/quote]");
rep(/<font.*?class=\"codeStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi, "[code][color=$1]$2[/color][/code]");
rep(/<font.*?class=\"quoteStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi, "[quote][color=$1]$2[/color][/quote]");
rep(/<span style=\"color: ?(.*?);\">(.*?)<\/span>/gi, "[color=$1]$2[/color]");
rep(/<font.*?color=\"(.*?)\".*?>(.*?)<\/font>/gi, "[color=$1]$2[/color]");
rep(/<span style=\"font-size:(.*?);\">(.*?)<\/span>/gi, "[size=$1]$2[/size]");
rep(/<font>(.*?)<\/font>/gi, "$1");
rep(/<img.*?src=\"(.*?)\".*?\/>/gi, "[img]$1[/img]");
rep(/<span class=\"codeStyle\">(.*?)<\/span>/gi, "[code]$1[/code]");
rep(/<span class=\"quoteStyle\">(.*?)<\/span>/gi, "[quote]$1[/quote]");
rep(/<strong class=\"codeStyle\">(.*?)<\/strong>/gi, "[code][b]$1[/b][/code]");
rep(/<strong class=\"quoteStyle\">(.*?)<\/strong>/gi, "[quote][b]$1[/b][/quote]");
rep(/<em class=\"codeStyle\">(.*?)<\/em>/gi, "[code][i]$1[/i][/code]");
rep(/<em class=\"quoteStyle\">(.*?)<\/em>/gi, "[quote][i]$1[/i][/quote]");
rep(/<u class=\"codeStyle\">(.*?)<\/u>/gi, "[code][u]$1[/u][/code]");
rep(/<u class=\"quoteStyle\">(.*?)<\/u>/gi, "[quote][u]$1[/u][/quote]");
rep(/<\/(strong|b)>/gi, "[/b]");
rep(/<(strong|b)>/gi, "[b]");
rep(/<\/(em|i)>/gi, "[/i]");
rep(/<(em|i)>/gi, "[i]");
rep(/<\/u>/gi, "[/u]");
rep(/<span style=\"text-decoration: ?underline;\">(.*?)<\/span>/gi, "[u]$1[/u]");
rep(/<u>/gi, "[u]");
rep(/<blockquote[^>]*>/gi, "[quote]");
rep(/<\/blockquote>/gi, "[/quote]");
rep(/<br \/>/gi, "\n");
rep(/<br\/>/gi, "\n");
rep(/<br>/gi, "\n");
rep(/<p>/gi, "");
rep(/<\/p>/gi, "\n");
rep(/&nbsp;|\u00a0/gi, " ");
rep(/&quot;/gi, "\"");
rep(/&lt;/gi, "<");
rep(/&gt;/gi, ">");
rep(/&amp;/gi, "&");
return s;
},
// BBCode -> HTML from PunBB dialect
_punbb_bbcode2html : function(s) {
s = tinymce.trim(s);
function rep(re, str) {
s = s.replace(re, str);
}
// example: [b] to <strong>
rep(/\n/gi, "<br />");
rep(/\[b\]/gi, "<strong>");
rep(/\[\/b\]/gi, "</strong>");
rep(/\[i\]/gi, "<em>");
rep(/\[\/i\]/gi, "</em>");
rep(/\[u\]/gi, "<u>");
rep(/\[\/u\]/gi, "</u>");
rep(/\[url=([^\]]+)\](.*?)\[\/url\]/gi, "<a href=\"$1\">$2</a>");
rep(/\[url\](.*?)\[\/url\]/gi, "<a href=\"$1\">$1</a>");
rep(/\[img\](.*?)\[\/img\]/gi, "<img src=\"$1\" />");
rep(/\[color=(.*?)\](.*?)\[\/color\]/gi, "<font color=\"$1\">$2</font>");
rep(/\[code\](.*?)\[\/code\]/gi, "<span class=\"codeStyle\">$1</span>&nbsp;");
rep(/\[quote.*?\](.*?)\[\/quote\]/gi, "<span class=\"quoteStyle\">$1</span>&nbsp;");
return s;
}
});
// Register plugin
tinymce.PluginManager.add('bbcode', tinymce.plugins.BBCodePlugin);
})();

View File

@ -0,0 +1 @@
!function(){tinymce.create("tinymce.plugins.BBCodePlugin",{init:function(a){var b=this,c=a.getParam("bbcode_dialect","punbb").toLowerCase();a.on("beforeSetContent",function(a){a.content=b["_"+c+"_bbcode2html"](a.content)}),a.on("postProcess",function(a){a.set&&(a.content=b["_"+c+"_bbcode2html"](a.content)),a.get&&(a.content=b["_"+c+"_html2bbcode"](a.content))})},getInfo:function(){return{longname:"BBCode Plugin",author:"Moxiecode Systems AB",authorurl:"http://www.tinymce.com",infourl:"http://www.tinymce.com/wiki.php/Plugin:bbcode"}},_punbb_html2bbcode:function(a){function b(b,c){a=a.replace(b,c)}return a=tinymce.trim(a),b(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]"),b(/<font.*?color=\"(.*?)\".*?class=\"codeStyle\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),b(/<font.*?color=\"(.*?)\".*?class=\"quoteStyle\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),b(/<font.*?class=\"codeStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),b(/<font.*?class=\"quoteStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),b(/<span style=\"color: ?(.*?);\">(.*?)<\/span>/gi,"[color=$1]$2[/color]"),b(/<font.*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[color=$1]$2[/color]"),b(/<span style=\"font-size:(.*?);\">(.*?)<\/span>/gi,"[size=$1]$2[/size]"),b(/<font>(.*?)<\/font>/gi,"$1"),b(/<img.*?src=\"(.*?)\".*?\/>/gi,"[img]$1[/img]"),b(/<span class=\"codeStyle\">(.*?)<\/span>/gi,"[code]$1[/code]"),b(/<span class=\"quoteStyle\">(.*?)<\/span>/gi,"[quote]$1[/quote]"),b(/<strong class=\"codeStyle\">(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"),b(/<strong class=\"quoteStyle\">(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"),b(/<em class=\"codeStyle\">(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"),b(/<em class=\"quoteStyle\">(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"),b(/<u class=\"codeStyle\">(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"),b(/<u class=\"quoteStyle\">(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"),b(/<\/(strong|b)>/gi,"[/b]"),b(/<(strong|b)>/gi,"[b]"),b(/<\/(em|i)>/gi,"[/i]"),b(/<(em|i)>/gi,"[i]"),b(/<\/u>/gi,"[/u]"),b(/<span style=\"text-decoration: ?underline;\">(.*?)<\/span>/gi,"[u]$1[/u]"),b(/<u>/gi,"[u]"),b(/<blockquote[^>]*>/gi,"[quote]"),b(/<\/blockquote>/gi,"[/quote]"),b(/<br \/>/gi,"\n"),b(/<br\/>/gi,"\n"),b(/<br>/gi,"\n"),b(/<p>/gi,""),b(/<\/p>/gi,"\n"),b(/&nbsp;|\u00a0/gi," "),b(/&quot;/gi,'"'),b(/&lt;/gi,"<"),b(/&gt;/gi,">"),b(/&amp;/gi,"&"),a},_punbb_bbcode2html:function(a){function b(b,c){a=a.replace(b,c)}return a=tinymce.trim(a),b(/\n/gi,"<br />"),b(/\[b\]/gi,"<strong>"),b(/\[\/b\]/gi,"</strong>"),b(/\[i\]/gi,"<em>"),b(/\[\/i\]/gi,"</em>"),b(/\[u\]/gi,"<u>"),b(/\[\/u\]/gi,"</u>"),b(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'<a href="$1">$2</a>'),b(/\[url\](.*?)\[\/url\]/gi,'<a href="$1">$1</a>'),b(/\[img\](.*?)\[\/img\]/gi,'<img src="$1" />'),b(/\[color=(.*?)\](.*?)\[\/color\]/gi,'<font color="$1">$2</font>'),b(/\[code\](.*?)\[\/code\]/gi,'<span class="codeStyle">$1</span>&nbsp;'),b(/\[quote.*?\](.*?)\[\/quote\]/gi,'<span class="quoteStyle">$1</span>&nbsp;'),a}}),tinymce.PluginManager.add("bbcode",tinymce.plugins.BBCodePlugin)}();

View File

@ -0,0 +1,370 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('charmap', function(editor) {
var charmap = [
['160', 'no-break space'],
['38', 'ampersand'],
['34', 'quotation mark'],
// finance
['162', 'cent sign'],
['8364', 'euro sign'],
['163', 'pound sign'],
['165', 'yen sign'],
// signs
['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'],
// quotations
['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'],
// math / logical
['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'],
// undefined
['180', 'acute accent'],
['184', 'cedilla'],
['170', 'feminine ordinal indicator'],
['186', 'masculine ordinal indicator'],
['8224', 'dagger'],
['8225', 'double dagger'],
// alphabetical special chars
['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'],
// symbols
['8501', 'alef symbol'],
['982', 'pi symbol'],
['8476', 'real part symbol'],
['978', 'upsilon - hook symbol'],
['8472', 'Weierstrass p'],
['8465', 'imaginary part'],
// arrows
['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'],
['173', 'soft hyphen']
];
function showDialog() {
var gridHtml, x, y, win;
function getParentTd(elm) {
while (elm) {
if (elm.nodeName == 'TD') {
return elm;
}
elm = elm.parentNode;
}
}
gridHtml = '<table role="presentation" cellspacing="0" class="mce-charmap"><tbody>';
var width = 25;
for (y = 0; y < 10; y++) {
gridHtml += '<tr>';
for (x = 0; x < width; x++) {
var chr = charmap[y * width + x];
gridHtml += '<td title="' + chr[1] + '"><div tabindex="-1" title="' + chr[1] + '" role="button">' +
(chr ? String.fromCharCode(parseInt(chr[0], 10)) : '&nbsp;') + '</div></td>';
}
gridHtml += '</tr>';
}
gridHtml += '</tbody></table>';
var charMapPanel = {
type: 'container',
html: gridHtml,
onclick: function(e) {
var target = e.target;
if (target.tagName == 'TD') {
target = target.firstChild;
}
if (target.tagName == 'DIV') {
editor.execCommand('mceInsertContent', false, target.firstChild.data);
if (!e.ctrlKey) {
win.close();
}
}
},
onmouseover: function(e) {
var td = getParentTd(e.target);
if (td) {
win.find('#preview').text(td.firstChild.firstChild.data);
}
}
};
win = editor.windowManager.open({
title: "Special character",
spacing: 10,
padding: 10,
items: [
charMapPanel,
{
type: 'label',
name: 'preview',
text: ' ',
style: 'font-size: 40px; text-align: center',
border: 1,
minWidth: 100,
minHeight: 80
}
],
buttons: [
{text: "Close", onclick: function() {
win.close();
}}
]
});
}
editor.addButton('charmap', {
icon: 'charmap',
tooltip: 'Special character',
onclick: showDialog
});
editor.addMenuItem('charmap', {
icon: 'charmap',
text: 'Special character',
onclick: showDialog,
context: 'insert'
});
});

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,60 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('code', function(editor) {
function showDialog() {
var win = editor.windowManager.open({
title: "Source code",
body: {
type: 'textbox',
name: 'code',
multiline: true,
minWidth: editor.getParam("code_dialog_width", 600),
minHeight: editor.getParam("code_dialog_height", Math.min(tinymce.DOM.getViewPort().h - 200, 500)),
spellcheck: false,
style: 'direction: ltr; text-align: left'
},
onSubmit: function(e) {
// We get a lovely "Wrong document" error in IE 11 if we
// don't move the focus to the editor before creating an undo
// transation since it tries to make a bookmark for the current selection
editor.focus();
editor.undoManager.transact(function() {
editor.setContent(e.data.code);
});
editor.selection.setCursorLocation();
editor.nodeChanged();
}
});
// Gecko has a major performance issue with textarea
// contents so we need to set it when all reflows are done
win.find('#code').value(editor.getContent({source_view: true}));
}
editor.addCommand("mceCodeEditor", showDialog);
editor.addButton('code', {
icon: 'code',
tooltip: 'Source code',
onclick: showDialog
});
editor.addMenuItem('code', {
icon: 'code',
text: 'Source code',
context: 'tools',
onclick: showDialog
});
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("code",function(a){function b(){var b=a.windowManager.open({title:"Source code",body:{type:"textbox",name:"code",multiline:!0,minWidth:a.getParam("code_dialog_width",600),minHeight:a.getParam("code_dialog_height",Math.min(tinymce.DOM.getViewPort().h-200,500)),spellcheck:!1,style:"direction: ltr; text-align: left"},onSubmit:function(b){a.focus(),a.undoManager.transact(function(){a.setContent(b.data.code)}),a.selection.setCursorLocation(),a.nodeChanged()}});b.find("#code").value(a.getContent({source_view:!0}))}a.addCommand("mceCodeEditor",b),a.addButton("code",{icon:"code",tooltip:"Source code",onclick:b}),a.addMenuItem("code",{icon:"code",text:"Source code",context:"tools",onclick:b})});

View File

@ -0,0 +1,112 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('colorpicker', function(editor) {
function colorPickerCallback(callback, value) {
function setColor(value) {
var color = new tinymce.util.Color(value), rgb = color.toRgb();
win.fromJSON({
r: rgb.r,
g: rgb.g,
b: rgb.b,
hex: color.toHex().substr(1)
});
showPreview(color.toHex());
}
function showPreview(hexColor) {
win.find('#preview')[0].getEl().style.background = hexColor;
}
var win = editor.windowManager.open({
title: 'Color',
items: {
type: 'container',
layout: 'flex',
direction: 'row',
align: 'stretch',
padding: 5,
spacing: 10,
items: [
{
type: 'colorpicker',
value: value,
onchange: function() {
var rgb = this.rgb();
if (win) {
win.find('#r').value(rgb.r);
win.find('#g').value(rgb.g);
win.find('#b').value(rgb.b);
win.find('#hex').value(this.value().substr(1));
showPreview(this.value());
}
}
},
{
type: 'form',
padding: 0,
labelGap: 5,
defaults: {
type: 'textbox',
size: 7,
value: '0',
flex: 1,
spellcheck: false,
onchange: function() {
var colorPickerCtrl = win.find('colorpicker')[0];
var name, value;
name = this.name();
value = this.value();
if (name == "hex") {
value = '#' + value;
setColor(value);
colorPickerCtrl.value(value);
return;
}
value = {
r: win.find('#r').value(),
g: win.find('#g').value(),
b: win.find('#b').value()
};
colorPickerCtrl.value(value);
setColor(value);
}
},
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() {
callback('#' + this.toJSON().hex);
}
});
setColor(value);
}
if (!editor.settings.color_picker_callback) {
editor.settings.color_picker_callback = colorPickerCallback;
}
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("colorpicker",function(a){function b(b,c){function d(a){var b=new tinymce.util.Color(a),c=b.toRgb();f.fromJSON({r:c.r,g:c.g,b:c.b,hex:b.toHex().substr(1)}),e(b.toHex())}function e(a){f.find("#preview")[0].getEl().style.background=a}var f=a.windowManager.open({title:"Color",items:{type:"container",layout:"flex",direction:"row",align:"stretch",padding:5,spacing:10,items:[{type:"colorpicker",value:c,onchange:function(){var a=this.rgb();f&&(f.find("#r").value(a.r),f.find("#g").value(a.g),f.find("#b").value(a.b),f.find("#hex").value(this.value().substr(1)),e(this.value()))}},{type:"form",padding:0,labelGap:5,defaults:{type:"textbox",size:7,value:"0",flex:1,spellcheck:!1,onchange:function(){var a,b,c=f.find("colorpicker")[0];return a=this.name(),b=this.value(),"hex"==a?(b="#"+b,d(b),void c.value(b)):(b={r:f.find("#r").value(),g:f.find("#g").value(),b:f.find("#b").value()},c.value(b),void d(b))}},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(){b("#"+this.toJSON().hex)}});d(c)}a.settings.color_picker_callback||(a.settings.color_picker_callback=b)});

View File

@ -0,0 +1,87 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('contextmenu', function(editor) {
var menu, contextmenuNeverUseNative = editor.settings.contextmenu_never_use_native;
editor.on('contextmenu', function(e) {
var contextmenu, doc = editor.getDoc();
// Block TinyMCE menu on ctrlKey
if (e.ctrlKey && !contextmenuNeverUseNative) {
return;
}
e.preventDefault();
/**
* WebKit/Blink on Mac has the odd behavior of selecting the target word or line this causes
* issues when for example inserting images see: #7022
*/
if (tinymce.Env.mac && tinymce.Env.webkit) {
if (e.button == 2 && doc.caretRangeFromPoint) {
editor.selection.setRng(doc.caretRangeFromPoint(e.x, e.y));
}
}
contextmenu = editor.settings.contextmenu || 'link image inserttable | cell row column deletetable';
// Render menu
if (!menu) {
var items = [];
tinymce.each(contextmenu.split(/[ ,]/), function(name) {
var item = editor.menuItems[name];
if (name == '|') {
item = {text: name};
}
if (item) {
item.shortcut = ''; // Hide shortcuts
items.push(item);
}
});
for (var i = 0; i < items.length; i++) {
if (items[i].text == '|') {
if (i === 0 || i == items.length - 1) {
items.splice(i, 1);
}
}
}
menu = new tinymce.ui.Menu({
items: items,
context: 'contextmenu'
}).addClass('contextmenu').renderTo();
editor.on('remove', function() {
menu.remove();
menu = null;
});
} else {
menu.show();
}
// Position menu
var pos = {x: e.pageX, y: e.pageY};
if (!editor.inline) {
pos = tinymce.DOM.getPos(editor.getContentAreaContainer());
pos.x += e.clientX;
pos.y += e.clientY;
}
menu.moveTo(pos.x, pos.y);
});
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("contextmenu",function(a){var b,c=a.settings.contextmenu_never_use_native;a.on("contextmenu",function(d){var e,f=a.getDoc();if(!d.ctrlKey||c){if(d.preventDefault(),tinymce.Env.mac&&tinymce.Env.webkit&&2==d.button&&f.caretRangeFromPoint&&a.selection.setRng(f.caretRangeFromPoint(d.x,d.y)),e=a.settings.contextmenu||"link image inserttable | cell row column deletetable",b)b.show();else{var g=[];tinymce.each(e.split(/[ ,]/),function(b){var c=a.menuItems[b];"|"==b&&(c={text:b}),c&&(c.shortcut="",g.push(c))});for(var h=0;h<g.length;h++)"|"==g[h].text&&(0===h||h==g.length-1)&&g.splice(h,1);b=new tinymce.ui.Menu({items:g,context:"contextmenu"}).addClass("contextmenu").renderTo(),a.on("remove",function(){b.remove(),b=null})}var i={x:d.pageX,y:d.pageY};a.inline||(i=tinymce.DOM.getPos(a.getContentAreaContainer()),i.x+=d.clientX,i.y+=d.clientY),b.moveTo(i.x,i.y)}})});

View File

@ -0,0 +1,64 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('directionality', function(editor) {
function setDir(dir) {
var dom = editor.dom, curDir, blocks = editor.selection.getSelectedBlocks();
if (blocks.length) {
curDir = dom.getAttrib(blocks[0], "dir");
tinymce.each(blocks, function(block) {
// Add dir to block if the parent block doesn't already have that dir
if (!dom.getParent(block.parentNode, "*[dir='" + dir + "']", dom.getRoot())) {
if (curDir != dir) {
dom.setAttrib(block, "dir", dir);
} else {
dom.setAttrib(block, "dir", null);
}
}
});
editor.nodeChanged();
}
}
function generateSelector(dir) {
var selector = [];
tinymce.each('h1 h2 h3 h4 h5 h6 div p'.split(' '), function(name) {
selector.push(name + '[dir=' + dir + ']');
});
return selector.join(',');
}
editor.addCommand('mceDirectionLTR', function() {
setDir("ltr");
});
editor.addCommand('mceDirectionRTL', function() {
setDir("rtl");
});
editor.addButton('ltr', {
title: 'Left to right',
cmd: 'mceDirectionLTR',
stateSelector: generateSelector('ltr')
});
editor.addButton('rtl', {
title: 'Right to left',
cmd: 'mceDirectionRTL',
stateSelector: generateSelector('rtl')
});
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("directionality",function(a){function b(b){var c,d=a.dom,e=a.selection.getSelectedBlocks();e.length&&(c=d.getAttrib(e[0],"dir"),tinymce.each(e,function(a){d.getParent(a.parentNode,"*[dir='"+b+"']",d.getRoot())||(c!=b?d.setAttrib(a,"dir",b):d.setAttrib(a,"dir",null))}),a.nodeChanged())}function c(a){var b=[];return tinymce.each("h1 h2 h3 h4 h5 h6 div p".split(" "),function(c){b.push(c+"[dir="+a+"]")}),b.join(",")}a.addCommand("mceDirectionLTR",function(){b("ltr")}),a.addCommand("mceDirectionRTL",function(){b("rtl")}),a.addButton("ltr",{title:"Left to right",cmd:"mceDirectionLTR",stateSelector:c("ltr")}),a.addButton("rtl",{title:"Right to left",cmd:"mceDirectionRTL",stateSelector:c("rtl")})});

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 B

View File

@ -0,0 +1,65 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('emoticons', function(editor, url) {
var emoticons = [
["cool", "cry", "embarassed", "foot-in-mouth"],
["frown", "innocent", "kiss", "laughing"],
["money-mouth", "sealed", "smile", "surprised"],
["tongue-out", "undecided", "wink", "yell"]
];
function getHtml() {
var emoticonsHtml;
emoticonsHtml = '<table role="list" class="mce-grid">';
tinymce.each(emoticons, function(row) {
emoticonsHtml += '<tr>';
tinymce.each(row, function(icon) {
var emoticonUrl = url + '/img/smiley-' + icon + '.gif';
emoticonsHtml += '<td><a href="#" data-mce-url="' + emoticonUrl + '" data-mce-alt="' + icon + '" tabindex="-1" ' +
'role="option" aria-label="' + icon + '"><img src="' +
emoticonUrl + '" style="width: 18px; height: 18px" role="presentation" /></a></td>';
});
emoticonsHtml += '</tr>';
});
emoticonsHtml += '</table>';
return emoticonsHtml;
}
editor.addButton('emoticons', {
type: 'panelbutton',
panel: {
role: 'application',
autohide: true,
html: getHtml,
onclick: function(e) {
var linkElm = editor.dom.getParent(e.target, 'a');
if (linkElm) {
editor.insertContent(
'<img src="' + linkElm.getAttribute('data-mce-url') + '" alt="' + linkElm.getAttribute('data-mce-alt') + '" />'
);
this.hide();
}
}
},
tooltip: 'Emoticons'
});
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("emoticons",function(a,b){function c(){var a;return a='<table role="list" class="mce-grid">',tinymce.each(d,function(c){a+="<tr>",tinymce.each(c,function(c){var d=b+"/img/smiley-"+c+".gif";a+='<td><a href="#" data-mce-url="'+d+'" data-mce-alt="'+c+'" tabindex="-1" role="option" aria-label="'+c+'"><img src="'+d+'" style="width: 18px; height: 18px" role="presentation" /></a></td>'}),a+="</tr>"}),a+="</table>"}var d=[["cool","cry","embarassed","foot-in-mouth"],["frown","innocent","kiss","laughing"],["money-mouth","sealed","smile","surprised"],["tongue-out","undecided","wink","yell"]];a.addButton("emoticons",{type:"panelbutton",panel:{role:"application",autohide:!0,html:c,onclick:function(b){var c=a.dom.getParent(b.target,"a");c&&(a.insertContent('<img src="'+c.getAttribute("data-mce-url")+'" alt="'+c.getAttribute("data-mce-alt")+'" />'),this.hide())}},tooltip:"Emoticons"})});

View File

@ -0,0 +1,490 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('fullpage', function(editor) {
var each = tinymce.each, Node = tinymce.html.Node;
var head, foot;
function showDialog() {
var data = htmlToData();
editor.windowManager.open({
title: 'Document properties',
data: data,
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) {
dataToHtml(tinymce.extend(data, e.data));
}
});
}
function htmlToData() {
var headerFragment = parseHeader(), data = {}, elm, matches;
function getAttr(elm, name) {
var value = elm.attr(name);
return value || '';
}
// Default some values
data.fontface = editor.getParam("fullpage_default_fontface", "");
data.fontsize = editor.getParam("fullpage_default_fontsize", "");
// Parse XML PI
elm = headerFragment.firstChild;
if (elm.type == 7) {
data.xml_pi = true;
matches = /encoding="([^"]+)"/.exec(elm.value);
if (matches) {
data.docencoding = matches[1];
}
}
// Parse doctype
elm = headerFragment.getAll('#doctype')[0];
if (elm) {
data.doctype = '<!DOCTYPE' + elm.value + ">";
}
// Parse title element
elm = headerFragment.getAll('title')[0];
if (elm && elm.firstChild) {
data.title = elm.firstChild.value;
}
// Parse meta elements
each(headerFragment.getAll('meta'), function(meta) {
var name = meta.attr('name'), httpEquiv = meta.attr('http-equiv'), matches;
if (name) {
data[name.toLowerCase()] = meta.attr('content');
} else if (httpEquiv == "Content-Type") {
matches = /charset\s*=\s*(.*)\s*/gi.exec(meta.attr('content'));
if (matches) {
data.docencoding = matches[1];
}
}
});
// Parse html attribs
elm = headerFragment.getAll('html')[0];
if (elm) {
data.langcode = getAttr(elm, 'lang') || getAttr(elm, 'xml:lang');
}
// Parse stylesheets
data.stylesheets = [];
tinymce.each(headerFragment.getAll('link'), function(link) {
if (link.attr('rel') == 'stylesheet') {
data.stylesheets.push(link.attr('href'));
}
});
// Parse body parts
elm = headerFragment.getAll('body')[0];
if (elm) {
data.langdir = getAttr(elm, 'dir');
data.style = getAttr(elm, 'style');
data.visited_color = getAttr(elm, 'vlink');
data.link_color = getAttr(elm, 'link');
data.active_color = getAttr(elm, 'alink');
}
return data;
}
function dataToHtml(data) {
var headerFragment, headElement, html, elm, value, dom = editor.dom;
function setAttr(elm, name, value) {
elm.attr(name, value ? value : undefined);
}
function addHeadNode(node) {
if (headElement.firstChild) {
headElement.insert(node, headElement.firstChild);
} else {
headElement.append(node);
}
}
headerFragment = parseHeader();
headElement = headerFragment.getAll('head')[0];
if (!headElement) {
elm = headerFragment.getAll('html')[0];
headElement = new Node('head', 1);
if (elm.firstChild) {
elm.insert(headElement, elm.firstChild, true);
} else {
elm.append(headElement);
}
}
// Add/update/remove XML-PI
elm = headerFragment.firstChild;
if (data.xml_pi) {
value = 'version="1.0"';
if (data.docencoding) {
value += ' encoding="' + data.docencoding + '"';
}
if (elm.type != 7) {
elm = new Node('xml', 7);
headerFragment.insert(elm, headerFragment.firstChild, true);
}
elm.value = value;
} else if (elm && elm.type == 7) {
elm.remove();
}
// Add/update/remove doctype
elm = headerFragment.getAll('#doctype')[0];
if (data.doctype) {
if (!elm) {
elm = new Node('#doctype', 10);
if (data.xml_pi) {
headerFragment.insert(elm, headerFragment.firstChild);
} else {
addHeadNode(elm);
}
}
elm.value = data.doctype.substring(9, data.doctype.length - 1);
} else if (elm) {
elm.remove();
}
// Add meta encoding
elm = null;
each(headerFragment.getAll('meta'), function(meta) {
if (meta.attr('http-equiv') == 'Content-Type') {
elm = meta;
}
});
if (data.docencoding) {
if (!elm) {
elm = new Node('meta', 1);
elm.attr('http-equiv', 'Content-Type');
elm.shortEnded = true;
addHeadNode(elm);
}
elm.attr('content', 'text/html; charset=' + data.docencoding);
} else if (elm) {
elm.remove();
}
// Add/update/remove title
elm = headerFragment.getAll('title')[0];
if (data.title) {
if (!elm) {
elm = new Node('title', 1);
addHeadNode(elm);
} else {
elm.empty();
}
elm.append(new Node('#text', 3)).value = data.title;
} else if (elm) {
elm.remove();
}
// Add/update/remove meta
each('keywords,description,author,copyright,robots'.split(','), function(name) {
var nodes = headerFragment.getAll('meta'), i, meta, value = data[name];
for (i = 0; i < nodes.length; i++) {
meta = nodes[i];
if (meta.attr('name') == name) {
if (value) {
meta.attr('content', value);
} else {
meta.remove();
}
return;
}
}
if (value) {
elm = new Node('meta', 1);
elm.attr('name', name);
elm.attr('content', value);
elm.shortEnded = true;
addHeadNode(elm);
}
});
var currentStyleSheetsMap = {};
tinymce.each(headerFragment.getAll('link'), function(stylesheet) {
if (stylesheet.attr('rel') == 'stylesheet') {
currentStyleSheetsMap[stylesheet.attr('href')] = stylesheet;
}
});
// Add new
tinymce.each(data.stylesheets, function(stylesheet) {
if (!currentStyleSheetsMap[stylesheet]) {
elm = new Node('link', 1);
elm.attr({
rel: 'stylesheet',
text: 'text/css',
href: stylesheet
});
elm.shortEnded = true;
addHeadNode(elm);
}
delete currentStyleSheetsMap[stylesheet];
});
// Delete old
tinymce.each(currentStyleSheetsMap, function(stylesheet) {
stylesheet.remove();
});
// Update body attributes
elm = headerFragment.getAll('body')[0];
if (elm) {
setAttr(elm, 'dir', data.langdir);
setAttr(elm, 'style', data.style);
setAttr(elm, 'vlink', data.visited_color);
setAttr(elm, 'link', data.link_color);
setAttr(elm, 'alink', data.active_color);
// Update iframe body as well
dom.setAttribs(editor.getBody(), {
style : data.style,
dir : data.dir,
vLink : data.visited_color,
link : data.link_color,
aLink : data.active_color
});
}
// Set html attributes
elm = headerFragment.getAll('html')[0];
if (elm) {
setAttr(elm, 'lang', data.langcode);
setAttr(elm, 'xml:lang', data.langcode);
}
// No need for a head element
if (!headElement.firstChild) {
headElement.remove();
}
// Serialize header fragment and crop away body part
html = new tinymce.html.Serializer({
validate: false,
indent: true,
apply_source_formatting : true,
indent_before: 'head,html,body,meta,title,script,link,style',
indent_after: 'head,html,body,meta,title,script,link,style'
}).serialize(headerFragment);
head = html.substring(0, html.indexOf('</body>'));
}
function parseHeader() {
// Parse the contents with a DOM parser
return new tinymce.html.DomParser({
validate: false,
root_name: '#document'
}).parse(head);
}
function setContent(evt) {
var startPos, endPos, content = evt.content, headerFragment, styles = '', dom = editor.dom, elm;
if (evt.selection) {
return;
}
function low(s) {
return s.replace(/<\/?[A-Z]+/g, function(a) {
return a.toLowerCase();
});
}
// Ignore raw updated if we already have a head, this will fix issues with undo/redo keeping the head/foot separate
if (evt.format == 'raw' && head) {
return;
}
if (evt.source_view && editor.getParam('fullpage_hide_in_source_view')) {
return;
}
// Fixed so new document/setContent('') doesn't remove existing header/footer except when it's in source code view
if (content.length === 0 && !evt.source_view) {
content = tinymce.trim(head) + '\n' + tinymce.trim(content) + '\n' + tinymce.trim(foot);
}
// Parse out head, body and footer
content = content.replace(/<(\/?)BODY/gi, '<$1body');
startPos = content.indexOf('<body');
if (startPos != -1) {
startPos = content.indexOf('>', startPos);
head = low(content.substring(0, startPos + 1));
endPos = content.indexOf('</body', startPos);
if (endPos == -1) {
endPos = content.length;
}
evt.content = content.substring(startPos + 1, endPos);
foot = low(content.substring(endPos));
} else {
head = getDefaultHeader();
foot = '\n</body>\n</html>';
}
// Parse header and update iframe
headerFragment = parseHeader();
each(headerFragment.getAll('style'), function(node) {
if (node.firstChild) {
styles += node.firstChild.value;
}
});
elm = headerFragment.getAll('body')[0];
if (elm) {
dom.setAttribs(editor.getBody(), {
style: elm.attr('style') || '',
dir: elm.attr('dir') || '',
vLink: elm.attr('vlink') || '',
link: elm.attr('link') || '',
aLink: elm.attr('alink') || ''
});
}
dom.remove('fullpage_styles');
var headElm = editor.getDoc().getElementsByTagName('head')[0];
if (styles) {
dom.add(headElm, 'style', {
id : 'fullpage_styles'
}, styles);
// Needed for IE 6/7
elm = dom.get('fullpage_styles');
if (elm.styleSheet) {
elm.styleSheet.cssText = styles;
}
}
var currentStyleSheetsMap = {};
tinymce.each(headElm.getElementsByTagName('link'), function(stylesheet) {
if (stylesheet.rel == 'stylesheet' && stylesheet.getAttribute('data-mce-fullpage')) {
currentStyleSheetsMap[stylesheet.href] = stylesheet;
}
});
// Add new
tinymce.each(headerFragment.getAll('link'), function(stylesheet) {
var href = stylesheet.attr('href');
if (!currentStyleSheetsMap[href] && stylesheet.attr('rel') == 'stylesheet') {
dom.add(headElm, 'link', {
rel: 'stylesheet',
text: 'text/css',
href: href,
'data-mce-fullpage': '1'
});
}
delete currentStyleSheetsMap[href];
});
// Delete old
tinymce.each(currentStyleSheetsMap, function(stylesheet) {
stylesheet.parentNode.removeChild(stylesheet);
});
}
function getDefaultHeader() {
var header = '', value, styles = '';
if (editor.getParam('fullpage_default_xml_pi')) {
header += '<?xml version="1.0" encoding="' + editor.getParam('fullpage_default_encoding', 'ISO-8859-1') + '" ?>\n';
}
header += editor.getParam('fullpage_default_doctype', '<!DOCTYPE html>');
header += '\n<html>\n<head>\n';
if ((value = editor.getParam('fullpage_default_title'))) {
header += '<title>' + value + '</title>\n';
}
if ((value = editor.getParam('fullpage_default_encoding'))) {
header += '<meta http-equiv="Content-Type" content="text/html; charset=' + value + '" />\n';
}
if ((value = editor.getParam('fullpage_default_font_family'))) {
styles += 'font-family: ' + value + ';';
}
if ((value = editor.getParam('fullpage_default_font_size'))) {
styles += 'font-size: ' + value + ';';
}
if ((value = editor.getParam('fullpage_default_text_color'))) {
styles += 'color: ' + value + ';';
}
header += '</head>\n<body' + (styles ? ' style="' + styles + '"' : '') + '>\n';
return header;
}
function getContent(evt) {
if (!evt.selection && (!evt.source_view || !editor.getParam('fullpage_hide_in_source_view'))) {
evt.content = tinymce.trim(head) + '\n' + tinymce.trim(evt.content) + '\n' + tinymce.trim(foot);
}
}
editor.addCommand('mceFullPageProperties', showDialog);
editor.addButton('fullpage', {
title: 'Document properties',
cmd : 'mceFullPageProperties'
});
editor.addMenuItem('fullpage', {
text: 'Document properties',
cmd : 'mceFullPageProperties',
context: 'file'
});
editor.on('BeforeSetContent', setContent);
editor.on('GetContent', getContent);
});

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,136 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('fullscreen', function(editor) {
var fullscreenState = false, DOM = tinymce.DOM, iframeWidth, iframeHeight, resizeHandler;
var containerWidth, containerHeight;
if (editor.settings.inline) {
return;
}
function getWindowSize() {
var w, h, win = window, doc = document;
var body = doc.body;
// Old IE
if (body.offsetWidth) {
w = body.offsetWidth;
h = body.offsetHeight;
}
// Modern browsers
if (win.innerWidth && win.innerHeight) {
w = win.innerWidth;
h = win.innerHeight;
}
return {w: w, h: h};
}
function toggleFullscreen() {
var body = document.body, documentElement = document.documentElement, editorContainerStyle;
var editorContainer, iframe, iframeStyle;
function resize() {
DOM.setStyle(iframe, 'height', getWindowSize().h - (editorContainer.clientHeight - iframe.clientHeight));
}
fullscreenState = !fullscreenState;
editorContainer = editor.getContainer();
editorContainerStyle = editorContainer.style;
iframe = editor.getContentAreaContainer().firstChild;
iframeStyle = iframe.style;
if (fullscreenState) {
iframeWidth = iframeStyle.width;
iframeHeight = iframeStyle.height;
iframeStyle.width = iframeStyle.height = '100%';
containerWidth = editorContainerStyle.width;
containerHeight = editorContainerStyle.height;
editorContainerStyle.width = editorContainerStyle.height = '';
DOM.addClass(body, 'mce-fullscreen');
DOM.addClass(documentElement, 'mce-fullscreen');
DOM.addClass(editorContainer, 'mce-fullscreen');
DOM.bind(window, 'resize', resize);
resize();
resizeHandler = resize;
} else {
iframeStyle.width = iframeWidth;
iframeStyle.height = iframeHeight;
if (containerWidth) {
editorContainerStyle.width = containerWidth;
}
if (containerHeight) {
editorContainerStyle.height = containerHeight;
}
DOM.removeClass(body, 'mce-fullscreen');
DOM.removeClass(documentElement, 'mce-fullscreen');
DOM.removeClass(editorContainer, 'mce-fullscreen');
DOM.unbind(window, 'resize', resizeHandler);
}
editor.fire('FullscreenStateChanged', {state: fullscreenState});
}
editor.on('init', function() {
editor.addShortcut('Ctrl+Alt+F', '', toggleFullscreen);
});
editor.on('remove', function() {
if (resizeHandler) {
DOM.unbind(window, 'resize', resizeHandler);
}
});
editor.addCommand('mceFullScreen', toggleFullscreen);
editor.addMenuItem('fullscreen', {
text: 'Fullscreen',
shortcut: 'Ctrl+Alt+F',
selectable: true,
onClick: toggleFullscreen,
onPostRender: function() {
var self = this;
editor.on('FullscreenStateChanged', function(e) {
self.active(e.state);
});
},
context: 'view'
});
editor.addButton('fullscreen', {
tooltip: 'Fullscreen',
shortcut: 'Ctrl+Alt+F',
onClick: toggleFullscreen,
onPostRender: function() {
var self = this;
editor.on('FullscreenStateChanged', function(e) {
self.active(e.state);
});
}
});
return {
isFullscreen: function() {
return fullscreenState;
}
};
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("fullscreen",function(a){function b(){var a,b,c=window,d=document,e=d.body;return e.offsetWidth&&(a=e.offsetWidth,b=e.offsetHeight),c.innerWidth&&c.innerHeight&&(a=c.innerWidth,b=c.innerHeight),{w:a,h:b}}function c(){function c(){j.setStyle(m,"height",b().h-(l.clientHeight-m.clientHeight))}var k,l,m,n,o=document.body,p=document.documentElement;i=!i,l=a.getContainer(),k=l.style,m=a.getContentAreaContainer().firstChild,n=m.style,i?(d=n.width,e=n.height,n.width=n.height="100%",g=k.width,h=k.height,k.width=k.height="",j.addClass(o,"mce-fullscreen"),j.addClass(p,"mce-fullscreen"),j.addClass(l,"mce-fullscreen"),j.bind(window,"resize",c),c(),f=c):(n.width=d,n.height=e,g&&(k.width=g),h&&(k.height=h),j.removeClass(o,"mce-fullscreen"),j.removeClass(p,"mce-fullscreen"),j.removeClass(l,"mce-fullscreen"),j.unbind(window,"resize",f)),a.fire("FullscreenStateChanged",{state:i})}var d,e,f,g,h,i=!1,j=tinymce.DOM;return a.settings.inline?void 0:(a.on("init",function(){a.addShortcut("Ctrl+Alt+F","",c)}),a.on("remove",function(){f&&j.unbind(window,"resize",f)}),a.addCommand("mceFullScreen",c),a.addMenuItem("fullscreen",{text:"Fullscreen",shortcut:"Ctrl+Alt+F",selectable:!0,onClick:c,onPostRender:function(){var b=this;a.on("FullscreenStateChanged",function(a){b.active(a.state)})},context:"view"}),a.addButton("fullscreen",{tooltip:"Fullscreen",shortcut:"Ctrl+Alt+F",onClick:c,onPostRender:function(){var b=this;a.on("FullscreenStateChanged",function(a){b.active(a.state)})}}),{isFullscreen:function(){return i}})});

View File

@ -0,0 +1,30 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('hr', function(editor) {
editor.addCommand('InsertHorizontalRule', function() {
editor.execCommand('mceInsertContent', false, '<hr />');
});
editor.addButton('hr', {
icon: 'hr',
tooltip: 'Horizontal line',
cmd: 'InsertHorizontalRule'
});
editor.addMenuItem('hr', {
icon: 'hr',
text: 'Horizontal line',
cmd: 'InsertHorizontalRule',
context: 'insert'
});
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("hr",function(a){a.addCommand("InsertHorizontalRule",function(){a.execCommand("mceInsertContent",!1,"<hr />")}),a.addButton("hr",{icon:"hr",tooltip:"Horizontal line",cmd:"InsertHorizontalRule"}),a.addMenuItem("hr",{icon:"hr",text:"Horizontal line",cmd:"InsertHorizontalRule",context:"insert"})});

View File

@ -0,0 +1,439 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('image', function(editor) {
function getImageSize(url, callback) {
var img = document.createElement('img');
function done(width, height) {
if (img.parentNode) {
img.parentNode.removeChild(img);
}
callback({width: width, height: height});
}
img.onload = function() {
done(img.clientWidth, img.clientHeight);
};
img.onerror = function() {
done();
};
var style = img.style;
style.visibility = 'hidden';
style.position = 'fixed';
style.bottom = style.left = 0;
style.width = style.height = 'auto';
document.body.appendChild(img);
img.src = url;
}
function buildListItems(inputList, itemCallback, startItems) {
function appendItems(values, output) {
output = output || [];
tinymce.each(values, function(item) {
var menuItem = {text: item.text || item.title};
if (item.menu) {
menuItem.menu = appendItems(item.menu);
} else {
menuItem.value = item.value;
itemCallback(menuItem);
}
output.push(menuItem);
});
return output;
}
return appendItems(inputList, startItems || []);
}
function createImageList(callback) {
return function() {
var imageList = editor.settings.image_list;
if (typeof(imageList) == "string") {
tinymce.util.XHR.send({
url: imageList,
success: function(text) {
callback(tinymce.util.JSON.parse(text));
}
});
} else if (typeof(imageList) == "function") {
imageList(callback);
} else {
callback(imageList);
}
};
}
function showDialog(imageList) {
var win, data = {}, dom = editor.dom, imgElm = editor.selection.getNode();
var width, height, imageListCtrl, classListCtrl, imageDimensions = editor.settings.image_dimensions !== false;
function recalcSize() {
var widthCtrl, heightCtrl, newWidth, newHeight;
widthCtrl = win.find('#width')[0];
heightCtrl = win.find('#height')[0];
if (!widthCtrl || !heightCtrl) {
return;
}
newWidth = widthCtrl.value();
newHeight = heightCtrl.value();
if (win.find('#constrain')[0].checked() && width && height && newWidth && newHeight) {
if (width != newWidth) {
newHeight = Math.round((newWidth / width) * newHeight);
heightCtrl.value(newHeight);
} else {
newWidth = Math.round((newHeight / height) * newWidth);
widthCtrl.value(newWidth);
}
}
width = newWidth;
height = newHeight;
}
function onSubmitForm() {
function waitLoad(imgElm) {
function selectImage() {
imgElm.onload = imgElm.onerror = null;
if (editor.selection) {
editor.selection.select(imgElm);
editor.nodeChanged();
}
}
imgElm.onload = function() {
if (!data.width && !data.height && imageDimensions) {
dom.setAttribs(imgElm, {
width: imgElm.clientWidth,
height: imgElm.clientHeight
});
}
selectImage();
};
imgElm.onerror = selectImage;
}
updateStyle();
recalcSize();
data = tinymce.extend(data, win.toJSON());
if (!data.alt) {
data.alt = '';
}
if (data.width === '') {
data.width = null;
}
if (data.height === '') {
data.height = null;
}
if (!data.style) {
data.style = null;
}
// Setup new data excluding style properties
data = {
src: data.src,
alt: data.alt,
width: data.width,
height: data.height,
style: data.style,
"class": data["class"]
};
editor.undoManager.transact(function() {
if (!data.src) {
if (imgElm) {
dom.remove(imgElm);
editor.focus();
editor.nodeChanged();
}
return;
}
if (!imgElm) {
data.id = '__mcenew';
editor.focus();
editor.selection.setContent(dom.createHTML('img', data));
imgElm = dom.get('__mcenew');
dom.setAttrib(imgElm, 'id', null);
} else {
dom.setAttribs(imgElm, data);
}
waitLoad(imgElm);
});
}
function removePixelSuffix(value) {
if (value) {
value = value.replace(/px$/, '');
}
return value;
}
function srcChange(e) {
var meta = e.meta || {};
if (imageListCtrl) {
imageListCtrl.value(editor.convertURL(this.value(), 'src'));
}
tinymce.each(meta, function(value, key) {
win.find('#' + key).value(value);
});
if (!meta.width && !meta.height) {
var srcURL = this.value(),
absoluteURLPattern = new RegExp('^(?:[a-z]+:)?//', 'i'),
baseURL = editor.settings.document_base_url;
//Pattern test the src url and make sure we haven't already prepended the url
if (baseURL && !absoluteURLPattern.test(srcURL) && srcURL.substring(0, baseURL.length) !== baseURL) {
this.value(baseURL + srcURL);
}
getImageSize(this.value(), function(data) {
if (data.width && data.height && imageDimensions) {
width = data.width;
height = data.height;
win.find('#width').value(width);
win.find('#height').value(height);
}
});
}
}
width = dom.getAttrib(imgElm, 'width');
height = dom.getAttrib(imgElm, 'height');
if (imgElm.nodeName == 'IMG' && !imgElm.getAttribute('data-mce-object') && !imgElm.getAttribute('data-mce-placeholder')) {
data = {
src: dom.getAttrib(imgElm, 'src'),
alt: dom.getAttrib(imgElm, 'alt'),
"class": dom.getAttrib(imgElm, 'class'),
width: width,
height: height
};
} else {
imgElm = null;
}
if (imageList) {
imageListCtrl = {
type: 'listbox',
label: 'Image list',
values: buildListItems(
imageList,
function(item) {
item.value = editor.convertURL(item.value || item.url, 'src');
},
[{text: 'None', value: ''}]
),
value: data.src && editor.convertURL(data.src, 'src'),
onselect: function(e) {
var altCtrl = win.find('#alt');
if (!altCtrl.value() || (e.lastControl && altCtrl.value() == e.lastControl.text())) {
altCtrl.value(e.control.text());
}
win.find('#src').value(e.control.value()).fire('change');
},
onPostRender: function() {
imageListCtrl = this;
}
};
}
if (editor.settings.image_class_list) {
classListCtrl = {
name: 'class',
type: 'listbox',
label: 'Class',
values: buildListItems(
editor.settings.image_class_list,
function(item) {
if (item.value) {
item.textStyle = function() {
return editor.formatter.getCssText({inline: 'img', classes: [item.value]});
};
}
}
)
};
}
// General settings shared between simple and advanced dialogs
var generalFormItems = [
{
name: 'src',
type: 'filepicker',
filetype: 'image',
label: 'Source',
autofocus: true,
onchange: srcChange
},
imageListCtrl
];
if (editor.settings.image_description !== false) {
generalFormItems.push({name: 'alt', type: 'textbox', label: 'Image description'});
}
if (imageDimensions) {
generalFormItems.push({
type: 'container',
label: 'Dimensions',
layout: 'flex',
direction: 'row',
align: 'center',
spacing: 5,
items: [
{name: 'width', type: 'textbox', maxLength: 5, size: 3, onchange: recalcSize, ariaLabel: 'Width'},
{type: 'label', text: 'x'},
{name: 'height', type: 'textbox', maxLength: 5, size: 3, onchange: recalcSize, ariaLabel: 'Height'},
{name: 'constrain', type: 'checkbox', checked: true, text: 'Constrain proportions'}
]
});
}
generalFormItems.push(classListCtrl);
function updateStyle() {
function addPixelSuffix(value) {
if (value.length > 0 && /^[0-9]+$/.test(value)) {
value += 'px';
}
return value;
}
if (!editor.settings.image_advtab) {
return;
}
var data = win.toJSON();
var css = dom.parseStyle(data.style);
delete css.margin;
css['margin-top'] = css['margin-bottom'] = addPixelSuffix(data.vspace);
css['margin-left'] = css['margin-right'] = addPixelSuffix(data.hspace);
css['border-width'] = addPixelSuffix(data.border);
win.find('#style').value(dom.serializeStyle(dom.parseStyle(dom.serializeStyle(css))));
}
if (editor.settings.image_advtab) {
// Parse styles from img
if (imgElm) {
data.hspace = removePixelSuffix(imgElm.style.marginLeft || imgElm.style.marginRight);
data.vspace = removePixelSuffix(imgElm.style.marginTop || imgElm.style.marginBottom);
data.border = removePixelSuffix(imgElm.style.borderWidth);
data.style = editor.dom.serializeStyle(editor.dom.parseStyle(editor.dom.getAttrib(imgElm, 'style')));
}
// Advanced dialog shows general+advanced tabs
win = editor.windowManager.open({
title: 'Insert/edit image',
data: data,
bodyType: 'tabpanel',
body: [
{
title: 'General',
type: 'form',
items: generalFormItems
},
{
title: 'Advanced',
type: 'form',
pack: 'start',
items: [
{
label: 'Style',
name: 'style',
type: 'textbox'
},
{
type: 'form',
layout: 'grid',
packV: 'start',
columns: 2,
padding: 0,
alignH: ['left', 'right'],
defaults: {
type: 'textbox',
maxWidth: 50,
onchange: updateStyle
},
items: [
{label: 'Vertical space', name: 'vspace'},
{label: 'Horizontal space', name: 'hspace'},
{label: 'Border', name: 'border'}
]
}
]
}
],
onSubmit: onSubmitForm
});
} else {
// Simple default dialog
win = editor.windowManager.open({
title: 'Insert/edit image',
data: data,
body: generalFormItems,
onSubmit: onSubmitForm
});
}
}
editor.addButton('image', {
icon: 'image',
tooltip: 'Insert/edit image',
onclick: createImageList(showDialog),
stateSelector: 'img:not([data-mce-object],[data-mce-placeholder])'
});
editor.addMenuItem('image', {
icon: 'image',
text: 'Insert image',
onclick: createImageList(showDialog),
context: 'insert',
prependToContext: true
});
editor.addCommand('mceImage', createImageList(showDialog));
});

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,195 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('importcss', function(editor) {
var self = this, each = tinymce.each;
function compileFilter(filter) {
if (typeof(filter) == "string") {
return function(value) {
return value.indexOf(filter) !== -1;
};
} else if (filter instanceof RegExp) {
return function(value) {
return filter.test(value);
};
}
return filter;
}
function getSelectors(doc, fileFilter) {
var selectors = [], contentCSSUrls = {};
function append(styleSheet, imported) {
var href = styleSheet.href, rules;
if (!href || !fileFilter(href, imported)) {
return;
}
each(styleSheet.imports, function(styleSheet) {
append(styleSheet, true);
});
try {
rules = styleSheet.cssRules || styleSheet.rules;
} catch (e) {
// Firefox fails on rules to remote domain for example:
// @import url(//fonts.googleapis.com/css?family=Pathway+Gothic+One);
}
each(rules, function(cssRule) {
if (cssRule.styleSheet) {
append(cssRule.styleSheet, true);
} else if (cssRule.selectorText) {
each(cssRule.selectorText.split(','), function(selector) {
selectors.push(tinymce.trim(selector));
});
}
});
}
each(editor.contentCSS, function(url) {
contentCSSUrls[url] = true;
});
if (!fileFilter) {
fileFilter = function(href, imported) {
return imported || contentCSSUrls[href];
};
}
try {
each(doc.styleSheets, function(styleSheet) {
append(styleSheet);
});
} catch (e) {}
return selectors;
}
function convertSelectorToFormat(selectorText) {
var format;
// Parse simple element.class1, .class1
var selector = /^(?:([a-z0-9\-_]+))?(\.[a-z0-9_\-\.]+)$/i.exec(selectorText);
if (!selector) {
return;
}
var elementName = selector[1];
var classes = selector[2].substr(1).split('.').join(' ');
var inlineSelectorElements = tinymce.makeMap('a,img');
// element.class - Produce block formats
if (selector[1]) {
format = {
title: selectorText
};
if (editor.schema.getTextBlockElements()[elementName]) {
// Text block format ex: h1.class1
format.block = elementName;
} else if (editor.schema.getBlockElements()[elementName] || inlineSelectorElements[elementName.toLowerCase()]) {
// Block elements such as table.class and special inline elements such as a.class or img.class
format.selector = elementName;
} else {
// Inline format strong.class1
format.inline = elementName;
}
} else if (selector[2]) {
// .class - Produce inline span with classes
format = {
inline: 'span',
title: selectorText.substr(1),
classes: classes
};
}
// Append to or override class attribute
if (editor.settings.importcss_merge_classes !== false) {
format.classes = classes;
} else {
format.attributes = {"class": classes};
}
return format;
}
editor.on('renderFormatsMenu', function(e) {
var settings = editor.settings, selectors = {};
var selectorConverter = settings.importcss_selector_converter || convertSelectorToFormat;
var selectorFilter = compileFilter(settings.importcss_selector_filter), ctrl = e.control;
if (!editor.settings.importcss_append) {
ctrl.items().remove();
}
// Setup new groups collection by cloning the configured one
var groups = [];
tinymce.each(settings.importcss_groups, function(group) {
group = tinymce.extend({}, group);
group.filter = compileFilter(group.filter);
groups.push(group);
});
each(getSelectors(e.doc || editor.getDoc(), compileFilter(settings.importcss_file_filter)), function(selector) {
if (selector.indexOf('.mce-') === -1) {
if (!selectors[selector] && (!selectorFilter || selectorFilter(selector))) {
var format = selectorConverter.call(self, selector), menu;
if (format) {
var formatName = format.name || tinymce.DOM.uniqueId();
if (groups) {
for (var i = 0; i < groups.length; i++) {
if (!groups[i].filter || groups[i].filter(selector)) {
if (!groups[i].item) {
groups[i].item = {text: groups[i].title, menu: []};
}
menu = groups[i].item.menu;
break;
}
}
}
editor.formatter.register(formatName, format);
var menuItem = tinymce.extend({}, ctrl.settings.itemDefaults, {
text: format.title,
format: formatName
});
if (menu) {
menu.push(menuItem);
} else {
ctrl.add(menuItem);
}
}
selectors[selector] = true;
}
}
});
each(groups, function(group) {
ctrl.add(group.item);
});
e.control.renderNew();
});
// Expose default convertSelectorToFormat implementation
self.convertSelectorToFormat = convertSelectorToFormat;
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("importcss",function(a){function b(a){return"string"==typeof a?function(b){return-1!==b.indexOf(a)}:a instanceof RegExp?function(b){return a.test(b)}:a}function c(b,c){function d(a,b){var g,h=a.href;if(h&&c(h,b)){f(a.imports,function(a){d(a,!0)});try{g=a.cssRules||a.rules}catch(i){}f(g,function(a){a.styleSheet?d(a.styleSheet,!0):a.selectorText&&f(a.selectorText.split(","),function(a){e.push(tinymce.trim(a))})})}}var e=[],g={};f(a.contentCSS,function(a){g[a]=!0}),c||(c=function(a,b){return b||g[a]});try{f(b.styleSheets,function(a){d(a)})}catch(h){}return e}function d(b){var c,d=/^(?:([a-z0-9\-_]+))?(\.[a-z0-9_\-\.]+)$/i.exec(b);if(d){var e=d[1],f=d[2].substr(1).split(".").join(" "),g=tinymce.makeMap("a,img");return d[1]?(c={title:b},a.schema.getTextBlockElements()[e]?c.block=e:a.schema.getBlockElements()[e]||g[e.toLowerCase()]?c.selector=e:c.inline=e):d[2]&&(c={inline:"span",title:b.substr(1),classes:f}),a.settings.importcss_merge_classes!==!1?c.classes=f:c.attributes={"class":f},c}}var e=this,f=tinymce.each;a.on("renderFormatsMenu",function(g){var h=a.settings,i={},j=h.importcss_selector_converter||d,k=b(h.importcss_selector_filter),l=g.control;a.settings.importcss_append||l.items().remove();var m=[];tinymce.each(h.importcss_groups,function(a){a=tinymce.extend({},a),a.filter=b(a.filter),m.push(a)}),f(c(g.doc||a.getDoc(),b(h.importcss_file_filter)),function(b){if(-1===b.indexOf(".mce-")&&!i[b]&&(!k||k(b))){var c,d=j.call(e,b);if(d){var f=d.name||tinymce.DOM.uniqueId();if(m)for(var g=0;g<m.length;g++)if(!m[g].filter||m[g].filter(b)){m[g].item||(m[g].item={text:m[g].title,menu:[]}),c=m[g].item.menu;break}a.formatter.register(f,d);var h=tinymce.extend({},l.settings.itemDefaults,{text:d.title,format:f});c?c.push(h):l.add(h)}i[b]=!0}}),f(m,function(a){l.add(a.item)}),g.control.renderNew()}),e.convertSelectorToFormat=d});

View File

@ -0,0 +1,121 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('insertdatetime', function(editor) {
var daysShort = "Sun Mon Tue Wed Thu Fri Sat Sun".split(' ');
var daysLong = "Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split(' ');
var monthsShort = "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(' ');
var monthsLong = "January February March April May June July August September October November December".split(' ');
var menuItems = [], lastFormat, defaultButtonTimeFormat;
function getDateTime(fmt, date) {
function addZeros(value, len) {
value = "" + value;
if (value.length < len) {
for (var i = 0; i < (len - value.length); i++) {
value = "0" + value;
}
}
return value;
}
date = date || new Date();
fmt = fmt.replace("%D", "%m/%d/%Y");
fmt = fmt.replace("%r", "%I:%M:%S %p");
fmt = fmt.replace("%Y", "" + date.getFullYear());
fmt = fmt.replace("%y", "" + date.getYear());
fmt = fmt.replace("%m", addZeros(date.getMonth() + 1, 2));
fmt = fmt.replace("%d", addZeros(date.getDate(), 2));
fmt = fmt.replace("%H", "" + addZeros(date.getHours(), 2));
fmt = fmt.replace("%M", "" + addZeros(date.getMinutes(), 2));
fmt = fmt.replace("%S", "" + addZeros(date.getSeconds(), 2));
fmt = fmt.replace("%I", "" + ((date.getHours() + 11) % 12 + 1));
fmt = fmt.replace("%p", "" + (date.getHours() < 12 ? "AM" : "PM"));
fmt = fmt.replace("%B", "" + editor.translate(monthsLong[date.getMonth()]));
fmt = fmt.replace("%b", "" + editor.translate(monthsShort[date.getMonth()]));
fmt = fmt.replace("%A", "" + editor.translate(daysLong[date.getDay()]));
fmt = fmt.replace("%a", "" + editor.translate(daysShort[date.getDay()]));
fmt = fmt.replace("%%", "%");
return fmt;
}
function insertDateTime(format) {
var html = getDateTime(format);
if (editor.settings.insertdatetime_element) {
var computerTime;
if (/%[HMSIp]/.test(format)) {
computerTime = getDateTime("%Y-%m-%dT%H:%M");
} else {
computerTime = getDateTime("%Y-%m-%d");
}
html = '<time datetime="' + computerTime + '">' + html + '</time>';
var timeElm = editor.dom.getParent(editor.selection.getStart(), 'time');
if (timeElm) {
editor.dom.setOuterHTML(timeElm, html);
return;
}
}
editor.insertContent(html);
}
editor.addCommand('mceInsertDate', function() {
insertDateTime(editor.getParam("insertdatetime_dateformat", editor.translate("%Y-%m-%d")));
});
editor.addCommand('mceInsertTime', function() {
insertDateTime(editor.getParam("insertdatetime_timeformat", editor.translate('%H:%M:%S')));
});
editor.addButton('insertdatetime', {
type: 'splitbutton',
title: 'Insert date/time',
onclick: function() {
insertDateTime(lastFormat || defaultButtonTimeFormat);
},
menu: menuItems
});
tinymce.each(editor.settings.insertdatetime_formats || [
"%H:%M:%S",
"%Y-%m-%d",
"%I:%M:%S %p",
"%D"
], function(fmt) {
if (!defaultButtonTimeFormat) {
defaultButtonTimeFormat = fmt;
}
menuItems.push({
text: getDateTime(fmt),
onclick: function() {
lastFormat = fmt;
insertDateTime(fmt);
}
});
});
editor.addMenuItem('insertdatetime', {
icon: 'date',
text: 'Insert date/time',
menu: menuItems,
context: 'insert'
});
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("insertdatetime",function(a){function b(b,c){function d(a,b){if(a=""+a,a.length<b)for(var c=0;c<b-a.length;c++)a="0"+a;return a}return c=c||new Date,b=b.replace("%D","%m/%d/%Y"),b=b.replace("%r","%I:%M:%S %p"),b=b.replace("%Y",""+c.getFullYear()),b=b.replace("%y",""+c.getYear()),b=b.replace("%m",d(c.getMonth()+1,2)),b=b.replace("%d",d(c.getDate(),2)),b=b.replace("%H",""+d(c.getHours(),2)),b=b.replace("%M",""+d(c.getMinutes(),2)),b=b.replace("%S",""+d(c.getSeconds(),2)),b=b.replace("%I",""+((c.getHours()+11)%12+1)),b=b.replace("%p",""+(c.getHours()<12?"AM":"PM")),b=b.replace("%B",""+a.translate(i[c.getMonth()])),b=b.replace("%b",""+a.translate(h[c.getMonth()])),b=b.replace("%A",""+a.translate(g[c.getDay()])),b=b.replace("%a",""+a.translate(f[c.getDay()])),b=b.replace("%%","%")}function c(c){var d=b(c);if(a.settings.insertdatetime_element){var e;e=b(/%[HMSIp]/.test(c)?"%Y-%m-%dT%H:%M":"%Y-%m-%d"),d='<time datetime="'+e+'">'+d+"</time>";var f=a.dom.getParent(a.selection.getStart(),"time");if(f)return void a.dom.setOuterHTML(f,d)}a.insertContent(d)}var d,e,f="Sun Mon Tue Wed Thu Fri Sat Sun".split(" "),g="Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split(" "),h="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),i="January February March April May June July August September October November December".split(" "),j=[];a.addCommand("mceInsertDate",function(){c(a.getParam("insertdatetime_dateformat",a.translate("%Y-%m-%d")))}),a.addCommand("mceInsertTime",function(){c(a.getParam("insertdatetime_timeformat",a.translate("%H:%M:%S")))}),a.addButton("insertdatetime",{type:"splitbutton",title:"Insert date/time",onclick:function(){c(d||e)},menu:j}),tinymce.each(a.settings.insertdatetime_formats||["%H:%M:%S","%Y-%m-%d","%I:%M:%S %p","%D"],function(a){e||(e=a),j.push({text:b(a),onclick:function(){d=a,c(a)}})}),a.addMenuItem("insertdatetime",{icon:"date",text:"Insert date/time",menu:j,context:"insert"})});

View File

@ -0,0 +1,225 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('layer', function(editor) {
function getParentLayer(node) {
do {
if (node.className && node.className.indexOf('mceItemLayer') != -1) {
return node;
}
} while ((node = node.parentNode));
}
function visualAid(e) {
var dom = editor.dom;
tinymce.each(dom.select('div,p', e), function(e) {
if (/^(absolute|relative|fixed)$/i.test(e.style.position)) {
if (e.hasVisual) {
dom.addClass(e, 'mceItemVisualAid');
} else {
dom.removeClass(e, 'mceItemVisualAid');
}
dom.addClass(e, 'mceItemLayer');
}
});
}
function move(d) {
var i, z = [], le = getParentLayer(editor.selection.getNode()), ci = -1, fi = -1, nl;
nl = [];
tinymce.walk(editor.getBody(), function(n) {
if (n.nodeType == 1 && /^(absolute|relative|static)$/i.test(n.style.position)) {
nl.push(n);
}
}, 'childNodes');
// Find z-indexes
for (i = 0; i < nl.length; i++) {
z[i] = nl[i].style.zIndex ? parseInt(nl[i].style.zIndex, 10) : 0;
if (ci < 0 && nl[i] == le) {
ci = i;
}
}
if (d < 0) {
// Move back
// Try find a lower one
for (i = 0; i < z.length; i++) {
if (z[i] < z[ci]) {
fi = i;
break;
}
}
if (fi > -1) {
nl[ci].style.zIndex = z[fi];
nl[fi].style.zIndex = z[ci];
} else {
if (z[ci] > 0) {
nl[ci].style.zIndex = z[ci] - 1;
}
}
} else {
// Move forward
// Try find a higher one
for (i = 0; i < z.length; i++) {
if (z[i] > z[ci]) {
fi = i;
break;
}
}
if (fi > -1) {
nl[ci].style.zIndex = z[fi];
nl[fi].style.zIndex = z[ci];
} else {
nl[ci].style.zIndex = z[ci] + 1;
}
}
editor.execCommand('mceRepaint');
}
function insertLayer() {
var dom = editor.dom, p = dom.getPos(dom.getParent(editor.selection.getNode(), '*'));
var body = editor.getBody();
editor.dom.add(body, 'div', {
style: {
position: 'absolute',
left: p.x,
top: (p.y > 20 ? p.y : 20),
width: 100,
height: 100
},
'class': 'mceItemVisualAid mceItemLayer'
}, editor.selection.getContent() || editor.getLang('layer.content'));
// Workaround for IE where it messes up the JS engine if you insert a layer on IE 6,7
if (tinymce.Env.ie) {
dom.setHTML(body, body.innerHTML);
}
}
function toggleAbsolute() {
var le = getParentLayer(editor.selection.getNode());
if (!le) {
le = editor.dom.getParent(editor.selection.getNode(), 'DIV,P,IMG');
}
if (le) {
if (le.style.position.toLowerCase() == "absolute") {
editor.dom.setStyles(le, {
position: '',
left: '',
top: '',
width: '',
height: ''
});
editor.dom.removeClass(le, 'mceItemVisualAid');
editor.dom.removeClass(le, 'mceItemLayer');
} else {
if (!le.style.left) {
le.style.left = 20 + 'px';
}
if (!le.style.top) {
le.style.top = 20 + 'px';
}
if (!le.style.width) {
le.style.width = le.width ? (le.width + 'px') : '100px';
}
if (!le.style.height) {
le.style.height = le.height ? (le.height + 'px') : '100px';
}
le.style.position = "absolute";
editor.dom.setAttrib(le, 'data-mce-style', '');
editor.addVisual(editor.getBody());
}
editor.execCommand('mceRepaint');
editor.nodeChanged();
}
}
// Register commands
editor.addCommand('mceInsertLayer', insertLayer);
editor.addCommand('mceMoveForward', function() {
move(1);
});
editor.addCommand('mceMoveBackward', function() {
move(-1);
});
editor.addCommand('mceMakeAbsolute', function() {
toggleAbsolute();
});
// Register buttons
editor.addButton('moveforward', {title: 'layer.forward_desc', cmd: 'mceMoveForward'});
editor.addButton('movebackward', {title: 'layer.backward_desc', cmd: 'mceMoveBackward'});
editor.addButton('absolute', {title: 'layer.absolute_desc', cmd: 'mceMakeAbsolute'});
editor.addButton('insertlayer', {title: 'layer.insertlayer_desc', cmd: 'mceInsertLayer'});
editor.on('init', function() {
if (tinymce.Env.ie) {
editor.getDoc().execCommand('2D-Position', false, true);
}
});
// Remove serialized styles when selecting a layer since it might be changed by a drag operation
editor.on('mouseup', function(e) {
var layer = getParentLayer(e.target);
if (layer) {
editor.dom.setAttrib(layer, 'data-mce-style', '');
}
});
// Fixes edit focus issues with layers on Gecko
// This will enable designMode while inside a layer and disable it when outside
editor.on('mousedown', function(e) {
var node = e.target, doc = editor.getDoc(), parent;
if (tinymce.Env.gecko) {
if (getParentLayer(node)) {
if (doc.designMode !== 'on') {
doc.designMode = 'on';
// Repaint caret
node = doc.body;
parent = node.parentNode;
parent.removeChild(node);
parent.appendChild(node);
}
} else if (doc.designMode == 'on') {
doc.designMode = 'off';
}
}
});
editor.on('NodeChange', visualAid);
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("layer",function(a){function b(a){do if(a.className&&-1!=a.className.indexOf("mceItemLayer"))return a;while(a=a.parentNode)}function c(b){var c=a.dom;tinymce.each(c.select("div,p",b),function(a){/^(absolute|relative|fixed)$/i.test(a.style.position)&&(a.hasVisual?c.addClass(a,"mceItemVisualAid"):c.removeClass(a,"mceItemVisualAid"),c.addClass(a,"mceItemLayer"))})}function d(c){var d,e,f=[],g=b(a.selection.getNode()),h=-1,i=-1;for(e=[],tinymce.walk(a.getBody(),function(a){1==a.nodeType&&/^(absolute|relative|static)$/i.test(a.style.position)&&e.push(a)},"childNodes"),d=0;d<e.length;d++)f[d]=e[d].style.zIndex?parseInt(e[d].style.zIndex,10):0,0>h&&e[d]==g&&(h=d);if(0>c){for(d=0;d<f.length;d++)if(f[d]<f[h]){i=d;break}i>-1?(e[h].style.zIndex=f[i],e[i].style.zIndex=f[h]):f[h]>0&&(e[h].style.zIndex=f[h]-1)}else{for(d=0;d<f.length;d++)if(f[d]>f[h]){i=d;break}i>-1?(e[h].style.zIndex=f[i],e[i].style.zIndex=f[h]):e[h].style.zIndex=f[h]+1}a.execCommand("mceRepaint")}function e(){var b=a.dom,c=b.getPos(b.getParent(a.selection.getNode(),"*")),d=a.getBody();a.dom.add(d,"div",{style:{position:"absolute",left:c.x,top:c.y>20?c.y:20,width:100,height:100},"class":"mceItemVisualAid mceItemLayer"},a.selection.getContent()||a.getLang("layer.content")),tinymce.Env.ie&&b.setHTML(d,d.innerHTML)}function f(){var c=b(a.selection.getNode());c||(c=a.dom.getParent(a.selection.getNode(),"DIV,P,IMG")),c&&("absolute"==c.style.position.toLowerCase()?(a.dom.setStyles(c,{position:"",left:"",top:"",width:"",height:""}),a.dom.removeClass(c,"mceItemVisualAid"),a.dom.removeClass(c,"mceItemLayer")):(c.style.left||(c.style.left="20px"),c.style.top||(c.style.top="20px"),c.style.width||(c.style.width=c.width?c.width+"px":"100px"),c.style.height||(c.style.height=c.height?c.height+"px":"100px"),c.style.position="absolute",a.dom.setAttrib(c,"data-mce-style",""),a.addVisual(a.getBody())),a.execCommand("mceRepaint"),a.nodeChanged())}a.addCommand("mceInsertLayer",e),a.addCommand("mceMoveForward",function(){d(1)}),a.addCommand("mceMoveBackward",function(){d(-1)}),a.addCommand("mceMakeAbsolute",function(){f()}),a.addButton("moveforward",{title:"layer.forward_desc",cmd:"mceMoveForward"}),a.addButton("movebackward",{title:"layer.backward_desc",cmd:"mceMoveBackward"}),a.addButton("absolute",{title:"layer.absolute_desc",cmd:"mceMakeAbsolute"}),a.addButton("insertlayer",{title:"layer.insertlayer_desc",cmd:"mceInsertLayer"}),a.on("init",function(){tinymce.Env.ie&&a.getDoc().execCommand("2D-Position",!1,!0)}),a.on("mouseup",function(c){var d=b(c.target);d&&a.dom.setAttrib(d,"data-mce-style","")}),a.on("mousedown",function(c){var d,e=c.target,f=a.getDoc();tinymce.Env.gecko&&(b(e)?"on"!==f.designMode&&(f.designMode="on",e=f.body,d=e.parentNode,d.removeChild(e),d.appendChild(e)):"on"==f.designMode&&(f.designMode="off"))}),a.on("NodeChange",c)});

View File

@ -0,0 +1,211 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*
* This plugin will force TinyMCE to produce deprecated legacy output such as font elements, u elements, align
* attributes and so forth. There are a few cases where these old items might be needed for example in email applications or with Flash
*
* However you should NOT use this plugin if you are building some system that produces web contents such as a CMS. All these elements are
* not apart of the newer specifications for HTML and XHTML.
*/
/*global tinymce:true */
(function(tinymce) {
// Override inline_styles setting to force TinyMCE to produce deprecated contents
tinymce.on('AddEditor', function(e) {
e.editor.settings.inline_styles = false;
});
tinymce.PluginManager.add('legacyoutput', function(editor, url, $) {
editor.on('init', function() {
var alignElements = 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img',
fontSizes = tinymce.explode(editor.settings.font_size_style_values),
schema = editor.schema;
// Override some internal formats to produce legacy elements and attributes
editor.formatter.register({
// Change alignment formats to use the deprecated align attribute
alignleft: {selector: alignElements, attributes: {align: 'left'}},
aligncenter: {selector: alignElements, attributes: {align: 'center'}},
alignright: {selector: alignElements, attributes: {align: 'right'}},
alignjustify: {selector: alignElements, attributes: {align: 'justify'}},
// Change the basic formatting elements to use deprecated element types
bold: [
{inline: 'b', remove: 'all'},
{inline: 'strong', remove: 'all'},
{inline: 'span', styles: {fontWeight: 'bold'}}
],
italic: [
{inline: 'i', remove: 'all'},
{inline: 'em', remove: 'all'},
{inline: 'span', styles: {fontStyle: 'italic'}}
],
underline: [
{inline: 'u', remove: 'all'},
{inline: 'span', styles: {textDecoration: 'underline'}, exact: true}
],
strikethrough: [
{inline: 'strike', remove: 'all'},
{inline: 'span', styles: {textDecoration: 'line-through'}, exact: true}
],
// Change font size and font family to use the deprecated font element
fontname: {inline: 'font', attributes: {face: '%value'}},
fontsize: {
inline: 'font',
attributes: {
size: function(vars) {
return tinymce.inArray(fontSizes, vars.value) + 1;
}
}
},
// Setup font elements for colors as well
forecolor: {inline: 'font', attributes: {color: '%value'}},
hilitecolor: {inline: 'font', styles: {backgroundColor: '%value'}}
});
// Check that deprecated elements are allowed if not add them
tinymce.each('b,i,u,strike'.split(','), function(name) {
schema.addValidElements(name + '[*]');
});
// Add font element if it's missing
if (!schema.getElementRule("font")) {
schema.addValidElements("font[face|size|color|style]");
}
// Add the missing and depreacted align attribute for the serialization engine
tinymce.each(alignElements.split(','), function(name) {
var rule = schema.getElementRule(name);
if (rule) {
if (!rule.attributes.align) {
rule.attributes.align = {};
rule.attributesOrder.push('align');
}
}
});
});
editor.addButton('fontsizeselect', function() {
var items = [], defaultFontsizeFormats = '8pt=1 10pt=2 12pt=3 14pt=4 18pt=5 24pt=6 36pt=7';
var fontsize_formats = editor.settings.fontsize_formats || defaultFontsizeFormats;
editor.$.each(fontsize_formats.split(' '), function(i, item) {
var text = item, value = item;
var values = item.split('=');
if (values.length > 1) {
text = values[0];
value = values[1];
}
items.push({text: text, value: value});
});
return {
type: 'listbox',
text: 'Font Sizes',
tooltip: 'Font Sizes',
values: items,
fixedWidth: true,
onPostRender: function() {
var self = this;
editor.on('NodeChange', function() {
var fontElm;
fontElm = editor.dom.getParent(editor.selection.getNode(), 'font');
if (fontElm) {
self.value(fontElm.size);
} else {
self.value('');
}
});
},
onclick: function(e) {
if (e.control.settings.value) {
editor.execCommand('FontSize', false, e.control.settings.value);
}
}
};
});
editor.addButton('fontselect', function() {
function createFormats(formats) {
formats = formats.replace(/;$/, '').split(';');
var i = formats.length;
while (i--) {
formats[i] = formats[i].split('=');
}
return formats;
}
var defaultFontsFormats =
'Andale Mono=andale mono,times;' +
'Arial=arial,helvetica,sans-serif;' +
'Arial Black=arial black,avant garde;' +
'Book Antiqua=book antiqua,palatino;' +
'Comic Sans MS=comic sans ms,sans-serif;' +
'Courier New=courier new,courier;' +
'Georgia=georgia,palatino;' +
'Helvetica=helvetica;' +
'Impact=impact,chicago;' +
'Symbol=symbol;' +
'Tahoma=tahoma,arial,helvetica,sans-serif;' +
'Terminal=terminal,monaco;' +
'Times New Roman=times new roman,times;' +
'Trebuchet MS=trebuchet ms,geneva;' +
'Verdana=verdana,geneva;' +
'Webdings=webdings;' +
'Wingdings=wingdings,zapf dingbats';
var items = [], fonts = createFormats(editor.settings.font_formats || defaultFontsFormats);
$.each(fonts, function(i, font) {
items.push({
text: {raw: font[0]},
value: font[1],
textStyle: font[1].indexOf('dings') == -1 ? 'font-family:' + font[1] : ''
});
});
return {
type: 'listbox',
text: 'Font Family',
tooltip: 'Font Family',
values: items,
fixedWidth: true,
onPostRender: function() {
var self = this;
editor.on('NodeChange', function() {
var fontElm;
fontElm = editor.dom.getParent(editor.selection.getNode(), 'font');
if (fontElm) {
self.value(fontElm.face);
} else {
self.value('');
}
});
},
onselect: function(e) {
if (e.control.settings.value) {
editor.execCommand('FontName', false, e.control.settings.value);
}
}
};
});
});
})(tinymce);

View File

@ -0,0 +1 @@
!function(a){a.on("AddEditor",function(a){a.editor.settings.inline_styles=!1}),a.PluginManager.add("legacyoutput",function(b,c,d){b.on("init",function(){var c="p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img",d=a.explode(b.settings.font_size_style_values),e=b.schema;b.formatter.register({alignleft:{selector:c,attributes:{align:"left"}},aligncenter:{selector:c,attributes:{align:"center"}},alignright:{selector:c,attributes:{align:"right"}},alignjustify:{selector:c,attributes:{align:"justify"}},bold:[{inline:"b",remove:"all"},{inline:"strong",remove:"all"},{inline:"span",styles:{fontWeight:"bold"}}],italic:[{inline:"i",remove:"all"},{inline:"em",remove:"all"},{inline:"span",styles:{fontStyle:"italic"}}],underline:[{inline:"u",remove:"all"},{inline:"span",styles:{textDecoration:"underline"},exact:!0}],strikethrough:[{inline:"strike",remove:"all"},{inline:"span",styles:{textDecoration:"line-through"},exact:!0}],fontname:{inline:"font",attributes:{face:"%value"}},fontsize:{inline:"font",attributes:{size:function(b){return a.inArray(d,b.value)+1}}},forecolor:{inline:"font",attributes:{color:"%value"}},hilitecolor:{inline:"font",styles:{backgroundColor:"%value"}}}),a.each("b,i,u,strike".split(","),function(a){e.addValidElements(a+"[*]")}),e.getElementRule("font")||e.addValidElements("font[face|size|color|style]"),a.each(c.split(","),function(a){var b=e.getElementRule(a);b&&(b.attributes.align||(b.attributes.align={},b.attributesOrder.push("align")))})}),b.addButton("fontsizeselect",function(){var a=[],c="8pt=1 10pt=2 12pt=3 14pt=4 18pt=5 24pt=6 36pt=7",d=b.settings.fontsize_formats||c;return b.$.each(d.split(" "),function(b,c){var d=c,e=c,f=c.split("=");f.length>1&&(d=f[0],e=f[1]),a.push({text:d,value:e})}),{type:"listbox",text:"Font Sizes",tooltip:"Font Sizes",values:a,fixedWidth:!0,onPostRender:function(){var a=this;b.on("NodeChange",function(){var c;c=b.dom.getParent(b.selection.getNode(),"font"),a.value(c?c.size:"")})},onclick:function(a){a.control.settings.value&&b.execCommand("FontSize",!1,a.control.settings.value)}}}),b.addButton("fontselect",function(){function a(a){a=a.replace(/;$/,"").split(";");for(var b=a.length;b--;)a[b]=a[b].split("=");return a}var c="Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats",e=[],f=a(b.settings.font_formats||c);return d.each(f,function(a,b){e.push({text:{raw:b[0]},value:b[1],textStyle:-1==b[1].indexOf("dings")?"font-family:"+b[1]:""})}),{type:"listbox",text:"Font Family",tooltip:"Font Family",values:e,fixedWidth:!0,onPostRender:function(){var a=this;b.on("NodeChange",function(){var c;c=b.dom.getParent(b.selection.getNode(),"font"),a.value(c?c.face:"")})},onselect:function(a){a.control.settings.value&&b.execCommand("FontName",!1,a.control.settings.value)}}})})}(tinymce);

View File

@ -0,0 +1,400 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('link', function(editor) {
function createLinkList(callback) {
return function() {
var linkList = editor.settings.link_list;
if (typeof(linkList) == "string") {
tinymce.util.XHR.send({
url: linkList,
success: function(text) {
callback(tinymce.util.JSON.parse(text));
}
});
} else if (typeof(linkList) == "function") {
linkList(callback);
} else {
callback(linkList);
}
};
}
function buildListItems(inputList, itemCallback, startItems) {
function appendItems(values, output) {
output = output || [];
tinymce.each(values, function(item) {
var menuItem = {text: item.text || item.title};
if (item.menu) {
menuItem.menu = appendItems(item.menu);
} else {
menuItem.value = item.value;
if (itemCallback) {
itemCallback(menuItem);
}
}
output.push(menuItem);
});
return output;
}
return appendItems(inputList, startItems || []);
}
function showDialog(linkList) {
var data = {}, selection = editor.selection, dom = editor.dom, selectedElm, anchorElm, initialText;
var win, onlyText, textListCtrl, linkListCtrl, relListCtrl, targetListCtrl, classListCtrl, linkTitleCtrl, value;
function linkListChangeHandler(e) {
var textCtrl = win.find('#text');
if (!textCtrl.value() || (e.lastControl && textCtrl.value() == e.lastControl.text())) {
textCtrl.value(e.control.text());
}
win.find('#href').value(e.control.value());
}
function buildAnchorListControl(url) {
var anchorList = [];
tinymce.each(editor.dom.select('a:not([href])'), function(anchor) {
var id = anchor.name || anchor.id;
if (id) {
anchorList.push({
text: id,
value: '#' + id,
selected: url.indexOf('#' + id) != -1
});
}
});
if (anchorList.length) {
anchorList.unshift({text: 'None', value: ''});
return {
name: 'anchor',
type: 'listbox',
label: 'Anchors',
values: anchorList,
onselect: linkListChangeHandler
};
}
}
function updateText() {
if (!initialText && data.text.length === 0 && onlyText) {
this.parent().parent().find('#text')[0].value(this.value());
}
}
function urlChange(e) {
var meta = e.meta || {};
if (linkListCtrl) {
linkListCtrl.value(editor.convertURL(this.value(), 'href'));
}
tinymce.each(e.meta, function(value, key) {
win.find('#' + key).value(value);
});
if (!meta.text) {
updateText.call(this);
}
}
function isOnlyTextSelected(anchorElm) {
var html = selection.getContent();
// Partial html and not a fully selected anchor element
if (/</.test(html) && (!/^<a [^>]+>[^<]+<\/a>$/.test(html) || html.indexOf('href=') == -1)) {
return false;
}
if (anchorElm) {
var nodes = anchorElm.childNodes, i;
if (nodes.length === 0) {
return false;
}
for (i = nodes.length - 1; i >= 0; i--) {
if (nodes[i].nodeType != 3) {
return false;
}
}
}
return true;
}
selectedElm = selection.getNode();
anchorElm = dom.getParent(selectedElm, 'a[href]');
onlyText = isOnlyTextSelected();
data.text = initialText = anchorElm ? (anchorElm.innerText || anchorElm.textContent) : selection.getContent({format: 'text'});
data.href = anchorElm ? dom.getAttrib(anchorElm, 'href') : '';
if ((value = dom.getAttrib(anchorElm, 'target'))) {
data.target = value;
} else if (editor.settings.default_link_target) {
data.target = editor.settings.default_link_target;
}
if ((value = dom.getAttrib(anchorElm, 'rel'))) {
data.rel = value;
}
if ((value = dom.getAttrib(anchorElm, 'class'))) {
data['class'] = value;
}
if ((value = dom.getAttrib(anchorElm, 'title'))) {
data.title = value;
}
if (onlyText) {
textListCtrl = {
name: 'text',
type: 'textbox',
size: 40,
label: 'Text to display',
onchange: function() {
data.text = this.value();
}
};
}
if (linkList) {
linkListCtrl = {
type: 'listbox',
label: 'Link list',
values: buildListItems(
linkList,
function(item) {
item.value = editor.convertURL(item.value || item.url, 'href');
},
[{text: 'None', value: ''}]
),
onselect: linkListChangeHandler,
value: editor.convertURL(data.href, 'href'),
onPostRender: function() {
linkListCtrl = this;
}
};
}
if (editor.settings.target_list !== false) {
if (!editor.settings.target_list) {
editor.settings.target_list = [
{text: 'None', value: ''},
{text: 'New window', value: '_blank'}
];
}
targetListCtrl = {
name: 'target',
type: 'listbox',
label: 'Target',
values: buildListItems(editor.settings.target_list)
};
}
if (editor.settings.rel_list) {
relListCtrl = {
name: 'rel',
type: 'listbox',
label: 'Rel',
values: buildListItems(editor.settings.rel_list)
};
}
if (editor.settings.link_class_list) {
classListCtrl = {
name: 'class',
type: 'listbox',
label: 'Class',
values: buildListItems(
editor.settings.link_class_list,
function(item) {
if (item.value) {
item.textStyle = function() {
return editor.formatter.getCssText({inline: 'a', classes: [item.value]});
};
}
}
)
};
}
if (editor.settings.link_title !== false) {
linkTitleCtrl = {
name: 'title',
type: 'textbox',
label: 'Title',
value: data.title
};
}
win = editor.windowManager.open({
title: 'Insert link',
data: data,
body: [
{
name: 'href',
type: 'filepicker',
filetype: 'file',
size: 40,
autofocus: true,
label: 'Url',
onchange: urlChange,
onkeyup: updateText
},
textListCtrl,
linkTitleCtrl,
buildAnchorListControl(data.href),
linkListCtrl,
relListCtrl,
targetListCtrl,
classListCtrl
],
onSubmit: function(e) {
var href;
data = tinymce.extend(data, e.data);
href = data.href;
// Delay confirm since onSubmit will move focus
function delayedConfirm(message, callback) {
var rng = editor.selection.getRng();
window.setTimeout(function() {
editor.windowManager.confirm(message, function(state) {
editor.selection.setRng(rng);
callback(state);
});
}, 0);
}
function insertLink() {
var linkAttrs = {
href: href,
target: data.target ? data.target : null,
rel: data.rel ? data.rel : null,
"class": data["class"] ? data["class"] : null,
title: data.title ? data.title : null
};
if (anchorElm) {
editor.focus();
if (onlyText && data.text != initialText) {
if ("innerText" in anchorElm) {
anchorElm.innerText = data.text;
} else {
anchorElm.textContent = data.text;
}
}
dom.setAttribs(anchorElm, linkAttrs);
selection.select(anchorElm);
editor.undoManager.add();
} else {
if (onlyText) {
editor.insertContent(dom.createHTML('a', linkAttrs, dom.encode(data.text)));
} else {
editor.execCommand('mceInsertLink', false, linkAttrs);
}
}
}
if (!href) {
editor.execCommand('unlink');
return;
}
// Is email and not //user@domain.com
if (href.indexOf('@') > 0 && href.indexOf('//') == -1 && href.indexOf('mailto:') == -1) {
delayedConfirm(
'The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?',
function(state) {
if (state) {
href = 'mailto:' + href;
}
insertLink();
}
);
return;
}
// Is www. prefixed
if (/^\s*www\./i.test(href)) {
delayedConfirm(
'The URL you entered seems to be an external link. Do you want to add the required http:// prefix?',
function(state) {
if (state) {
href = 'http://' + href;
}
insertLink();
}
);
return;
}
insertLink();
}
});
}
editor.addButton('link', {
icon: 'link',
tooltip: 'Insert/edit link',
shortcut: 'Ctrl+K',
onclick: createLinkList(showDialog),
stateSelector: 'a[href]'
});
editor.addButton('unlink', {
icon: 'unlink',
tooltip: 'Remove link',
cmd: 'unlink',
stateSelector: 'a[href]'
});
editor.addShortcut('Ctrl+K', '', createLinkList(showDialog));
editor.addCommand('mceLink', createLinkList(showDialog));
this.showDialog = showDialog;
editor.addMenuItem('link', {
icon: 'link',
text: 'Insert link',
shortcut: 'Ctrl+K',
onclick: createLinkList(showDialog),
stateSelector: 'a[href]',
context: 'insert',
prependToContext: true
});
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("link",function(a){function b(b){return function(){var c=a.settings.link_list;"string"==typeof c?tinymce.util.XHR.send({url:c,success:function(a){b(tinymce.util.JSON.parse(a))}}):"function"==typeof c?c(b):b(c)}}function c(a,b,c){function d(a,c){return c=c||[],tinymce.each(a,function(a){var e={text:a.text||a.title};a.menu?e.menu=d(a.menu):(e.value=a.value,b&&b(e)),c.push(e)}),c}return d(a,c||[])}function d(b){function d(a){var b=l.find("#text");(!b.value()||a.lastControl&&b.value()==a.lastControl.text())&&b.value(a.control.text()),l.find("#href").value(a.control.value())}function e(b){var c=[];return tinymce.each(a.dom.select("a:not([href])"),function(a){var d=a.name||a.id;d&&c.push({text:d,value:"#"+d,selected:-1!=b.indexOf("#"+d)})}),c.length?(c.unshift({text:"None",value:""}),{name:"anchor",type:"listbox",label:"Anchors",values:c,onselect:d}):void 0}function f(){!k&&0===u.text.length&&m&&this.parent().parent().find("#text")[0].value(this.value())}function g(b){var c=b.meta||{};o&&o.value(a.convertURL(this.value(),"href")),tinymce.each(b.meta,function(a,b){l.find("#"+b).value(a)}),c.text||f.call(this)}function h(a){var b=v.getContent();if(/</.test(b)&&(!/^<a [^>]+>[^<]+<\/a>$/.test(b)||-1==b.indexOf("href=")))return!1;if(a){var c,d=a.childNodes;if(0===d.length)return!1;for(c=d.length-1;c>=0;c--)if(3!=d[c].nodeType)return!1}return!0}var i,j,k,l,m,n,o,p,q,r,s,t,u={},v=a.selection,w=a.dom;i=v.getNode(),j=w.getParent(i,"a[href]"),m=h(),u.text=k=j?j.innerText||j.textContent:v.getContent({format:"text"}),u.href=j?w.getAttrib(j,"href"):"",(t=w.getAttrib(j,"target"))?u.target=t:a.settings.default_link_target&&(u.target=a.settings.default_link_target),(t=w.getAttrib(j,"rel"))&&(u.rel=t),(t=w.getAttrib(j,"class"))&&(u["class"]=t),(t=w.getAttrib(j,"title"))&&(u.title=t),m&&(n={name:"text",type:"textbox",size:40,label:"Text to display",onchange:function(){u.text=this.value()}}),b&&(o={type:"listbox",label:"Link list",values:c(b,function(b){b.value=a.convertURL(b.value||b.url,"href")},[{text:"None",value:""}]),onselect:d,value:a.convertURL(u.href,"href"),onPostRender:function(){o=this}}),a.settings.target_list!==!1&&(a.settings.target_list||(a.settings.target_list=[{text:"None",value:""},{text:"New window",value:"_blank"}]),q={name:"target",type:"listbox",label:"Target",values:c(a.settings.target_list)}),a.settings.rel_list&&(p={name:"rel",type:"listbox",label:"Rel",values:c(a.settings.rel_list)}),a.settings.link_class_list&&(r={name:"class",type:"listbox",label:"Class",values:c(a.settings.link_class_list,function(b){b.value&&(b.textStyle=function(){return a.formatter.getCssText({inline:"a",classes:[b.value]})})})}),a.settings.link_title!==!1&&(s={name:"title",type:"textbox",label:"Title",value:u.title}),l=a.windowManager.open({title:"Insert link",data:u,body:[{name:"href",type:"filepicker",filetype:"file",size:40,autofocus:!0,label:"Url",onchange:g,onkeyup:f},n,s,e(u.href),o,p,q,r],onSubmit:function(b){function c(b,c){var d=a.selection.getRng();window.setTimeout(function(){a.windowManager.confirm(b,function(b){a.selection.setRng(d),c(b)})},0)}function d(){var b={href:e,target:u.target?u.target:null,rel:u.rel?u.rel:null,"class":u["class"]?u["class"]:null,title:u.title?u.title:null};j?(a.focus(),m&&u.text!=k&&("innerText"in j?j.innerText=u.text:j.textContent=u.text),w.setAttribs(j,b),v.select(j),a.undoManager.add()):m?a.insertContent(w.createHTML("a",b,w.encode(u.text))):a.execCommand("mceInsertLink",!1,b)}var e;return u=tinymce.extend(u,b.data),(e=u.href)?e.indexOf("@")>0&&-1==e.indexOf("//")&&-1==e.indexOf("mailto:")?void c("The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?",function(a){a&&(e="mailto:"+e),d()}):/^\s*www\./i.test(e)?void c("The URL you entered seems to be an external link. Do you want to add the required http:// prefix?",function(a){a&&(e="http://"+e),d()}):void d():void a.execCommand("unlink")}})}a.addButton("link",{icon:"link",tooltip:"Insert/edit link",shortcut:"Ctrl+K",onclick:b(d),stateSelector:"a[href]"}),a.addButton("unlink",{icon:"unlink",tooltip:"Remove link",cmd:"unlink",stateSelector:"a[href]"}),a.addShortcut("Ctrl+K","",b(d)),a.addCommand("mceLink",b(d)),this.showDialog=d,a.addMenuItem("link",{icon:"link",text:"Insert link",shortcut:"Ctrl+K",onclick:b(d),stateSelector:"a[href]",context:"insert",prependToContext:!0})});

View File

@ -0,0 +1,791 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
/*eslint consistent-this:0 */
tinymce.PluginManager.add('lists', function(editor) {
var self = this;
function isListNode(node) {
return node && (/^(OL|UL|DL)$/).test(node.nodeName);
}
function isFirstChild(node) {
return node.parentNode.firstChild == node;
}
function isLastChild(node) {
return node.parentNode.lastChild == node;
}
function isTextBlock(node) {
return node && !!editor.schema.getTextBlockElements()[node.nodeName];
}
editor.on('init', function() {
var dom = editor.dom, selection = editor.selection;
/**
* Returns a range bookmark. This will convert indexed bookmarks into temporary span elements with
* index 0 so that they can be restored properly after the DOM has been modified. Text bookmarks will not have spans
* added to them since they can be restored after a dom operation.
*
* So this: <p><b>|</b><b>|</b></p>
* becomes: <p><b><span data-mce-type="bookmark">|</span></b><b data-mce-type="bookmark">|</span></b></p>
*
* @param {DOMRange} rng DOM Range to get bookmark on.
* @return {Object} Bookmark object.
*/
function createBookmark(rng) {
var bookmark = {};
function setupEndPoint(start) {
var offsetNode, container, offset;
container = rng[start ? 'startContainer' : 'endContainer'];
offset = rng[start ? 'startOffset' : 'endOffset'];
if (container.nodeType == 1) {
offsetNode = dom.create('span', {'data-mce-type': 'bookmark'});
if (container.hasChildNodes()) {
offset = Math.min(offset, container.childNodes.length - 1);
if (start) {
container.insertBefore(offsetNode, container.childNodes[offset]);
} else {
dom.insertAfter(offsetNode, container.childNodes[offset]);
}
} else {
container.appendChild(offsetNode);
}
container = offsetNode;
offset = 0;
}
bookmark[start ? 'startContainer' : 'endContainer'] = container;
bookmark[start ? 'startOffset' : 'endOffset'] = offset;
}
setupEndPoint(true);
if (!rng.collapsed) {
setupEndPoint();
}
return bookmark;
}
/**
* Moves the selection to the current bookmark and removes any selection container wrappers.
*
* @param {Object} bookmark Bookmark object to move selection to.
*/
function moveToBookmark(bookmark) {
function restoreEndPoint(start) {
var container, offset, node;
function nodeIndex(container) {
var node = container.parentNode.firstChild, idx = 0;
while (node) {
if (node == container) {
return idx;
}
// Skip data-mce-type=bookmark nodes
if (node.nodeType != 1 || node.getAttribute('data-mce-type') != 'bookmark') {
idx++;
}
node = node.nextSibling;
}
return -1;
}
container = node = bookmark[start ? 'startContainer' : 'endContainer'];
offset = bookmark[start ? 'startOffset' : 'endOffset'];
if (!container) {
return;
}
if (container.nodeType == 1) {
offset = nodeIndex(container);
container = container.parentNode;
dom.remove(node);
}
bookmark[start ? 'startContainer' : 'endContainer'] = container;
bookmark[start ? 'startOffset' : 'endOffset'] = offset;
}
restoreEndPoint(true);
restoreEndPoint();
var rng = dom.createRng();
rng.setStart(bookmark.startContainer, bookmark.startOffset);
if (bookmark.endContainer) {
rng.setEnd(bookmark.endContainer, bookmark.endOffset);
}
selection.setRng(rng);
}
function createNewTextBlock(contentNode, blockName) {
var node, textBlock, fragment = dom.createFragment(), hasContentNode;
var blockElements = editor.schema.getBlockElements();
if (editor.settings.forced_root_block) {
blockName = blockName || editor.settings.forced_root_block;
}
if (blockName) {
textBlock = dom.create(blockName);
if (textBlock.tagName === editor.settings.forced_root_block) {
dom.setAttribs(textBlock, editor.settings.forced_root_block_attrs);
}
fragment.appendChild(textBlock);
}
if (contentNode) {
while ((node = contentNode.firstChild)) {
var nodeName = node.nodeName;
if (!hasContentNode && (nodeName != 'SPAN' || node.getAttribute('data-mce-type') != 'bookmark')) {
hasContentNode = true;
}
if (blockElements[nodeName]) {
fragment.appendChild(node);
textBlock = null;
} else {
if (blockName) {
if (!textBlock) {
textBlock = dom.create(blockName);
fragment.appendChild(textBlock);
}
textBlock.appendChild(node);
} else {
fragment.appendChild(node);
}
}
}
}
if (!editor.settings.forced_root_block) {
fragment.appendChild(dom.create('br'));
} else {
// BR is needed in empty blocks on non IE browsers
if (!hasContentNode && (!tinymce.Env.ie || tinymce.Env.ie > 10)) {
textBlock.appendChild(dom.create('br', {'data-mce-bogus': '1'}));
}
}
return fragment;
}
function getSelectedListItems() {
return tinymce.grep(selection.getSelectedBlocks(), function(block) {
return /^(LI|DT|DD)$/.test(block.nodeName);
});
}
function splitList(ul, li, newBlock) {
var tmpRng, fragment;
var bookmarks = dom.select('span[data-mce-type="bookmark"]', ul);
newBlock = newBlock || createNewTextBlock(li);
tmpRng = dom.createRng();
tmpRng.setStartAfter(li);
tmpRng.setEndAfter(ul);
fragment = tmpRng.extractContents();
if (!dom.isEmpty(fragment)) {
dom.insertAfter(fragment, ul);
}
dom.insertAfter(newBlock, ul);
if (dom.isEmpty(li.parentNode)) {
tinymce.each(bookmarks, function(node) {
li.parentNode.parentNode.insertBefore(node, li.parentNode);
});
dom.remove(li.parentNode);
}
dom.remove(li);
}
function mergeWithAdjacentLists(listBlock) {
var sibling, node;
sibling = listBlock.nextSibling;
if (sibling && isListNode(sibling) && sibling.nodeName == listBlock.nodeName) {
while ((node = sibling.firstChild)) {
listBlock.appendChild(node);
}
dom.remove(sibling);
}
sibling = listBlock.previousSibling;
if (sibling && isListNode(sibling) && sibling.nodeName == listBlock.nodeName) {
while ((node = sibling.firstChild)) {
listBlock.insertBefore(node, listBlock.firstChild);
}
dom.remove(sibling);
}
}
/**
* Normalizes the all lists in the specified element.
*/
function normalizeList(element) {
tinymce.each(tinymce.grep(dom.select('ol,ul', element)), function(ul) {
var sibling, parentNode = ul.parentNode;
// Move UL/OL to previous LI if it's the only child of a LI
if (parentNode.nodeName == 'LI' && parentNode.firstChild == ul) {
sibling = parentNode.previousSibling;
if (sibling && sibling.nodeName == 'LI') {
sibling.appendChild(ul);
if (dom.isEmpty(parentNode)) {
dom.remove(parentNode);
}
}
}
// Append OL/UL to previous LI if it's in a parent OL/UL i.e. old HTML4
if (isListNode(parentNode)) {
sibling = parentNode.previousSibling;
if (sibling && sibling.nodeName == 'LI') {
sibling.appendChild(ul);
}
}
});
}
function outdent(li) {
var ul = li.parentNode, ulParent = ul.parentNode, newBlock;
function removeEmptyLi(li) {
if (dom.isEmpty(li)) {
dom.remove(li);
}
}
if (li.nodeName == 'DD') {
dom.rename(li, 'DT');
return true;
}
if (isFirstChild(li) && isLastChild(li)) {
if (ulParent.nodeName == "LI") {
dom.insertAfter(li, ulParent);
removeEmptyLi(ulParent);
dom.remove(ul);
} else if (isListNode(ulParent)) {
dom.remove(ul, true);
} else {
ulParent.insertBefore(createNewTextBlock(li), ul);
dom.remove(ul);
}
return true;
} else if (isFirstChild(li)) {
if (ulParent.nodeName == "LI") {
dom.insertAfter(li, ulParent);
li.appendChild(ul);
removeEmptyLi(ulParent);
} else if (isListNode(ulParent)) {
ulParent.insertBefore(li, ul);
} else {
ulParent.insertBefore(createNewTextBlock(li), ul);
dom.remove(li);
}
return true;
} else if (isLastChild(li)) {
if (ulParent.nodeName == "LI") {
dom.insertAfter(li, ulParent);
} else if (isListNode(ulParent)) {
dom.insertAfter(li, ul);
} else {
dom.insertAfter(createNewTextBlock(li), ul);
dom.remove(li);
}
return true;
} else {
if (ulParent.nodeName == 'LI') {
ul = ulParent;
newBlock = createNewTextBlock(li, 'LI');
} else if (isListNode(ulParent)) {
newBlock = createNewTextBlock(li, 'LI');
} else {
newBlock = createNewTextBlock(li);
}
splitList(ul, li, newBlock);
normalizeList(ul.parentNode);
return true;
}
return false;
}
function indent(li) {
var sibling, newList;
function mergeLists(from, to) {
var node;
if (isListNode(from)) {
while ((node = li.lastChild.firstChild)) {
to.appendChild(node);
}
dom.remove(from);
}
}
if (li.nodeName == 'DT') {
dom.rename(li, 'DD');
return true;
}
sibling = li.previousSibling;
if (sibling && isListNode(sibling)) {
sibling.appendChild(li);
return true;
}
if (sibling && sibling.nodeName == 'LI' && isListNode(sibling.lastChild)) {
sibling.lastChild.appendChild(li);
mergeLists(li.lastChild, sibling.lastChild);
return true;
}
sibling = li.nextSibling;
if (sibling && isListNode(sibling)) {
sibling.insertBefore(li, sibling.firstChild);
return true;
}
if (sibling && sibling.nodeName == 'LI' && isListNode(li.lastChild)) {
return false;
}
sibling = li.previousSibling;
if (sibling && sibling.nodeName == 'LI') {
newList = dom.create(li.parentNode.nodeName);
sibling.appendChild(newList);
newList.appendChild(li);
mergeLists(li.lastChild, newList);
return true;
}
return false;
}
function indentSelection() {
var listElements = getSelectedListItems();
if (listElements.length) {
var bookmark = createBookmark(selection.getRng(true));
for (var i = 0; i < listElements.length; i++) {
if (!indent(listElements[i]) && i === 0) {
break;
}
}
moveToBookmark(bookmark);
editor.nodeChanged();
return true;
}
}
function outdentSelection() {
var listElements = getSelectedListItems();
if (listElements.length) {
var bookmark = createBookmark(selection.getRng(true));
var i, y, root = editor.getBody();
i = listElements.length;
while (i--) {
var node = listElements[i].parentNode;
while (node && node != root) {
y = listElements.length;
while (y--) {
if (listElements[y] === node) {
listElements.splice(i, 1);
break;
}
}
node = node.parentNode;
}
}
for (i = 0; i < listElements.length; i++) {
if (!outdent(listElements[i]) && i === 0) {
break;
}
}
moveToBookmark(bookmark);
editor.nodeChanged();
return true;
}
}
function applyList(listName) {
var rng = selection.getRng(true), bookmark = createBookmark(rng), listItemName = 'LI';
listName = listName.toUpperCase();
if (listName == 'DL') {
listItemName = 'DT';
}
function getSelectedTextBlocks() {
var textBlocks = [], root = editor.getBody();
function getEndPointNode(start) {
var container, offset;
container = rng[start ? 'startContainer' : 'endContainer'];
offset = rng[start ? 'startOffset' : 'endOffset'];
// Resolve node index
if (container.nodeType == 1) {
container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;
}
while (container.parentNode != root) {
if (isTextBlock(container)) {
return container;
}
if (/^(TD|TH)$/.test(container.parentNode.nodeName)) {
return container;
}
container = container.parentNode;
}
return container;
}
var startNode = getEndPointNode(true);
var endNode = getEndPointNode();
var block, siblings = [];
for (var node = startNode; node; node = node.nextSibling) {
siblings.push(node);
if (node == endNode) {
break;
}
}
tinymce.each(siblings, function(node) {
if (isTextBlock(node)) {
textBlocks.push(node);
block = null;
return;
}
if (dom.isBlock(node) || node.nodeName == 'BR') {
if (node.nodeName == 'BR') {
dom.remove(node);
}
block = null;
return;
}
var nextSibling = node.nextSibling;
if (tinymce.dom.BookmarkManager.isBookmarkNode(node)) {
if (isTextBlock(nextSibling) || (!nextSibling && node.parentNode == root)) {
block = null;
return;
}
}
if (!block) {
block = dom.create('p');
node.parentNode.insertBefore(block, node);
textBlocks.push(block);
}
block.appendChild(node);
});
return textBlocks;
}
tinymce.each(getSelectedTextBlocks(), function(block) {
var listBlock, sibling;
sibling = block.previousSibling;
if (sibling && isListNode(sibling) && sibling.nodeName == listName) {
listBlock = sibling;
block = dom.rename(block, listItemName);
sibling.appendChild(block);
} else {
listBlock = dom.create(listName);
block.parentNode.insertBefore(listBlock, block);
listBlock.appendChild(block);
block = dom.rename(block, listItemName);
}
mergeWithAdjacentLists(listBlock);
});
moveToBookmark(bookmark);
}
function removeList() {
var bookmark = createBookmark(selection.getRng(true)), root = editor.getBody();
tinymce.each(getSelectedListItems(), function(li) {
var node, rootList;
if (dom.isEmpty(li)) {
outdent(li);
return;
}
for (node = li; node && node != root; node = node.parentNode) {
if (isListNode(node)) {
rootList = node;
}
}
splitList(rootList, li);
});
moveToBookmark(bookmark);
}
function toggleList(listName) {
var parentList = dom.getParent(selection.getStart(), 'OL,UL,DL');
if (parentList) {
if (parentList.nodeName == listName) {
removeList(listName);
} else {
var bookmark = createBookmark(selection.getRng(true));
mergeWithAdjacentLists(dom.rename(parentList, listName));
moveToBookmark(bookmark);
}
} else {
applyList(listName);
}
}
function queryListCommandState(listName) {
return function() {
var parentList = dom.getParent(editor.selection.getStart(), 'UL,OL,DL');
return parentList && parentList.nodeName == listName;
};
}
self.backspaceDelete = function(isForward) {
function findNextCaretContainer(rng, isForward) {
var node = rng.startContainer, offset = rng.startOffset;
var nonEmptyBlocks, walker;
if (node.nodeType == 3 && (isForward ? offset < node.data.length : offset > 0)) {
return node;
}
nonEmptyBlocks = editor.schema.getNonEmptyElements();
walker = new tinymce.dom.TreeWalker(rng.startContainer);
while ((node = walker[isForward ? 'next' : 'prev']())) {
if (node.nodeName == 'LI' && !node.hasChildNodes()) {
return node;
}
if (nonEmptyBlocks[node.nodeName]) {
return node;
}
if (node.nodeType == 3 && node.data.length > 0) {
return node;
}
}
}
function mergeLiElements(fromElm, toElm) {
var node, listNode, ul = fromElm.parentNode;
if (isListNode(toElm.lastChild)) {
listNode = toElm.lastChild;
}
node = toElm.lastChild;
if (node && node.nodeName == 'BR' && fromElm.hasChildNodes()) {
dom.remove(node);
}
if (dom.isEmpty(toElm)) {
dom.$(toElm).empty();
}
if (!dom.isEmpty(fromElm)) {
while ((node = fromElm.firstChild)) {
toElm.appendChild(node);
}
}
if (listNode) {
toElm.appendChild(listNode);
}
dom.remove(fromElm);
if (dom.isEmpty(ul)) {
dom.remove(ul);
}
}
if (selection.isCollapsed()) {
var li = dom.getParent(selection.getStart(), 'LI');
if (li) {
var rng = selection.getRng(true);
var otherLi = dom.getParent(findNextCaretContainer(rng, isForward), 'LI');
if (otherLi && otherLi != li) {
var bookmark = createBookmark(rng);
if (isForward) {
mergeLiElements(otherLi, li);
} else {
mergeLiElements(li, otherLi);
}
moveToBookmark(bookmark);
return true;
} else if (!otherLi) {
if (!isForward && removeList(li.parentNode.nodeName)) {
return true;
}
}
}
}
};
editor.addCommand('Indent', function() {
if (!indentSelection()) {
return true;
}
});
editor.addCommand('Outdent', function() {
if (!outdentSelection()) {
return true;
}
});
editor.addCommand('InsertUnorderedList', function() {
toggleList('UL');
});
editor.addCommand('InsertOrderedList', function() {
toggleList('OL');
});
editor.addCommand('InsertDefinitionList', function() {
toggleList('DL');
});
editor.addQueryStateHandler('InsertUnorderedList', queryListCommandState('UL'));
editor.addQueryStateHandler('InsertOrderedList', queryListCommandState('OL'));
editor.addQueryStateHandler('InsertDefinitionList', queryListCommandState('DL'));
editor.on('keydown', function(e) {
// Check for tab but not ctrl/cmd+tab since it switches browser tabs
if (e.keyCode != 9 || tinymce.util.VK.metaKeyPressed(e)) {
return;
}
if (editor.dom.getParent(editor.selection.getStart(), 'LI,DT,DD')) {
e.preventDefault();
if (e.shiftKey) {
outdentSelection();
} else {
indentSelection();
}
}
});
});
editor.addButton('indent', {
icon: 'indent',
title: 'Increase indent',
cmd: 'Indent',
onPostRender: function() {
var ctrl = this;
editor.on('nodechange', function() {
var blocks = editor.selection.getSelectedBlocks();
var disable = false;
for (var i = 0, l = blocks.length; !disable && i < l; i++) {
var tag = blocks[i].nodeName;
disable = (tag == 'LI' && isFirstChild(blocks[i]) || tag == 'UL' || tag == 'OL' || tag == 'DD');
}
ctrl.disabled(disable);
});
}
});
editor.on('keydown', function(e) {
if (e.keyCode == tinymce.util.VK.BACKSPACE) {
if (self.backspaceDelete()) {
e.preventDefault();
}
} else if (e.keyCode == tinymce.util.VK.DELETE) {
if (self.backspaceDelete(true)) {
e.preventDefault();
}
}
});
});

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,774 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*jshint maxlen:255 */
/*eslint max-len:0 */
/*global tinymce:true */
tinymce.PluginManager.add('media', function(editor, url) {
var urlPatterns = [
{regex: /youtu\.be\/([\w\-.]+)/, type: 'iframe', w: 425, h: 350, url: '//www.youtube.com/embed/$1'},
{regex: /youtube\.com(.+)v=([^&]+)/, type: 'iframe', w: 425, h: 350, url: '//www.youtube.com/embed/$2'},
{regex: /vimeo\.com\/([0-9]+)/, type: 'iframe', w: 425, h: 350, url: '//player.vimeo.com/video/$1?title=0&byline=0&portrait=0&color=8dc7dc'},
{regex: /vimeo\.com\/(.*)\/([0-9]+)/, type: "iframe", w: 425, h: 350, url: "//player.vimeo.com/video/$2?title=0&amp;byline=0"},
{regex: /maps\.google\.([a-z]{2,3})\/maps\/(.+)msid=(.+)/, type: 'iframe', w: 425, h: 350, url: '//maps.google.com/maps/ms?msid=$2&output=embed"'}
];
var embedChange = (tinymce.Env.ie && tinymce.Env.ie <= 8) ? 'onChange' : 'onInput';
function guessMime(url) {
if (url.indexOf('.mp3') != -1) {
return 'audio/mpeg';
}
if (url.indexOf('.wav') != -1) {
return 'audio/wav';
}
if (url.indexOf('.mp4') != -1) {
return 'video/mp4';
}
if (url.indexOf('.webm') != -1) {
return 'video/webm';
}
if (url.indexOf('.ogg') != -1) {
return 'video/ogg';
}
if (url.indexOf('.swf') != -1) {
return 'application/x-shockwave-flash';
}
return '';
}
function getVideoScriptMatch(src) {
var prefixes = editor.settings.media_scripts;
if (prefixes) {
for (var i = 0; i < prefixes.length; i++) {
if (src.indexOf(prefixes[i].filter) !== -1) {
return prefixes[i];
}
}
}
}
function showDialog() {
var win, width, height, data;
var generalFormItems = [
{
name: 'source1',
type: 'filepicker',
filetype: 'media',
size: 40,
autofocus: true,
label: 'Source',
onchange: function(e) {
tinymce.each(e.meta, function(value, key) {
win.find('#' + key).value(value);
});
}
}
];
function recalcSize(e) {
var widthCtrl, heightCtrl, newWidth, newHeight;
widthCtrl = win.find('#width')[0];
heightCtrl = win.find('#height')[0];
newWidth = widthCtrl.value();
newHeight = heightCtrl.value();
if (win.find('#constrain')[0].checked() && width && height && newWidth && newHeight) {
if (e.control == widthCtrl) {
newHeight = Math.round((newWidth / width) * newHeight);
heightCtrl.value(newHeight);
} else {
newWidth = Math.round((newHeight / height) * newWidth);
widthCtrl.value(newWidth);
}
}
width = newWidth;
height = newHeight;
}
if (editor.settings.media_alt_source !== false) {
generalFormItems.push({name: 'source2', type: 'filepicker', filetype: 'media', size: 40, label: 'Alternative source'});
}
if (editor.settings.media_poster !== false) {
generalFormItems.push({name: 'poster', type: 'filepicker', filetype: 'image', size: 40, label: 'Poster'});
}
if (editor.settings.media_dimensions !== false) {
generalFormItems.push({
type: 'container',
label: 'Dimensions',
layout: 'flex',
align: 'center',
spacing: 5,
items: [
{name: 'width', type: 'textbox', maxLength: 3, size: 3, onchange: recalcSize},
{type: 'label', text: 'x'},
{name: 'height', type: 'textbox', maxLength: 3, size: 3, onchange: recalcSize},
{name: 'constrain', type: 'checkbox', checked: true, text: 'Constrain proportions'}
]
});
}
data = getData(editor.selection.getNode());
width = data.width;
height = data.height;
var embedTextBox = {
id: 'mcemediasource',
type: 'textbox',
flex: 1,
name: 'embed',
value: getSource(),
multiline: true,
label: 'Source'
};
function updateValueOnChange() {
data = htmlToData(this.value());
this.parent().parent().fromJSON(data);
}
embedTextBox[embedChange] = updateValueOnChange;
win = editor.windowManager.open({
title: 'Insert/edit video',
data: data,
bodyType: 'tabpanel',
body: [
{
title: 'General',
type: "form",
onShowTab: function() {
data = htmlToData(this.next().find('#embed').value());
this.fromJSON(data);
},
items: generalFormItems
},
{
title: 'Embed',
type: "panel",
layout: 'flex',
direction: 'column',
align: 'stretch',
padding: 10,
spacing: 10,
onShowTab: function() {
this.find('#embed').value(dataToHtml(this.parent().toJSON()));
},
items: [
{
type: 'label',
text: 'Paste your embed code below:',
forId: 'mcemediasource'
},
embedTextBox
]
}
],
onSubmit: function() {
var beforeObjects, afterObjects, i, y;
beforeObjects = editor.dom.select('img[data-mce-object]');
editor.insertContent(dataToHtml(this.toJSON()));
afterObjects = editor.dom.select('img[data-mce-object]');
// Find new image placeholder so we can select it
for (i = 0; i < beforeObjects.length; i++) {
for (y = afterObjects.length - 1; y >= 0; y--) {
if (beforeObjects[i] == afterObjects[y]) {
afterObjects.splice(y, 1);
}
}
}
editor.selection.select(afterObjects[0]);
editor.nodeChanged();
}
});
}
function getSource() {
var elm = editor.selection.getNode();
if (elm.getAttribute('data-mce-object')) {
return editor.selection.getContent();
}
}
function dataToHtml(data) {
var html = '';
if (!data.source1) {
tinymce.extend(data, htmlToData(data.embed));
if (!data.source1) {
return '';
}
}
if (!data.source2) {
data.source2 = '';
}
if (!data.poster) {
data.poster = '';
}
data.source1 = editor.convertURL(data.source1, "source");
data.source2 = editor.convertURL(data.source2, "source");
data.source1mime = guessMime(data.source1);
data.source2mime = guessMime(data.source2);
data.poster = editor.convertURL(data.poster, "poster");
data.flashPlayerUrl = editor.convertURL(url + '/moxieplayer.swf', "movie");
tinymce.each(urlPatterns, function(pattern) {
var match, i, url;
if ((match = pattern.regex.exec(data.source1))) {
url = pattern.url;
for (i = 0; match[i]; i++) {
/*jshint loopfunc:true*/
/*eslint no-loop-func:0 */
url = url.replace('$' + i, function() {
return match[i];
});
}
data.source1 = url;
data.type = pattern.type;
data.width = data.width || pattern.w;
data.height = data.height || pattern.h;
}
});
if (data.embed) {
html = updateHtml(data.embed, data, true);
} else {
var videoScript = getVideoScriptMatch(data.source1);
if (videoScript) {
data.type = 'script';
data.width = videoScript.width;
data.height = videoScript.height;
}
data.width = data.width || 300;
data.height = data.height || 150;
tinymce.each(data, function(value, key) {
data[key] = editor.dom.encode(value);
});
if (data.type == "iframe") {
html += '<iframe src="' + data.source1 + '" width="' + data.width + '" height="' + data.height + '"></iframe>';
} else if (data.source1mime == "application/x-shockwave-flash") {
html += '<object data="' + data.source1 + '" width="' + data.width + '" height="' + data.height + '" type="application/x-shockwave-flash">';
if (data.poster) {
html += '<img src="' + data.poster + '" width="' + data.width + '" height="' + data.height + '" />';
}
html += '</object>';
} else if (data.source1mime.indexOf('audio') != -1) {
if (editor.settings.audio_template_callback) {
html = editor.settings.audio_template_callback(data);
} else {
html += (
'<audio controls="controls" src="' + data.source1 + '">' +
(data.source2 ? '\n<source src="' + data.source2 + '"' + (data.source2mime ? ' type="' + data.source2mime + '"' : '') + ' />\n' : '') +
'</audio>'
);
}
} else if (data.type == "script") {
html += '<script src="' + data.source1 + '"></script>';
} else {
if (editor.settings.video_template_callback) {
html = editor.settings.video_template_callback(data);
} else {
html = (
'<video width="' + data.width + '" height="' + data.height + '"' + (data.poster ? ' poster="' + data.poster + '"' : '') + ' controls="controls">\n' +
'<source src="' + data.source1 + '"' + (data.source1mime ? ' type="' + data.source1mime + '"' : '') + ' />\n' +
(data.source2 ? '<source src="' + data.source2 + '"' + (data.source2mime ? ' type="' + data.source2mime + '"' : '') + ' />\n' : '') +
'</video>'
);
}
}
}
return html;
}
function htmlToData(html) {
var data = {};
new tinymce.html.SaxParser({
validate: false,
allow_conditional_comments: true,
special: 'script,noscript',
start: function(name, attrs) {
if (!data.source1 && name == "param") {
data.source1 = attrs.map.movie;
}
if (name == "iframe" || name == "object" || name == "embed" || name == "video" || name == "audio") {
if (!data.type) {
data.type = name;
}
data = tinymce.extend(attrs.map, data);
}
if (name == "script") {
var videoScript = getVideoScriptMatch(attrs.map.src);
if (!videoScript) {
return;
}
data = {
type: "script",
source1: attrs.map.src,
width: videoScript.width,
height: videoScript.height
};
}
if (name == "source") {
if (!data.source1) {
data.source1 = attrs.map.src;
} else if (!data.source2) {
data.source2 = attrs.map.src;
}
}
if (name == "img" && !data.poster) {
data.poster = attrs.map.src;
}
}
}).parse(html);
data.source1 = data.source1 || data.src || data.data;
data.source2 = data.source2 || '';
data.poster = data.poster || '';
return data;
}
function getData(element) {
if (element.getAttribute('data-mce-object')) {
return htmlToData(editor.serializer.serialize(element, {selection: true}));
}
return {};
}
function sanitize(html) {
if (editor.settings.media_filter_html === false) {
return html;
}
var writer = new tinymce.html.Writer();
new tinymce.html.SaxParser({
validate: false,
allow_conditional_comments: false,
special: 'script,noscript',
comment: function(text) {
writer.comment(text);
},
cdata: function(text) {
writer.cdata(text);
},
text: function(text, raw) {
writer.text(text, raw);
},
start: function(name, attrs, empty) {
if (name == 'script' || name == 'noscript') {
return;
}
for (var i = 0; i < attrs.length; i++) {
if (attrs[i].name.indexOf('on') === 0) {
return;
}
}
writer.start(name, attrs, empty);
},
end: function(name) {
if (name == 'script' || name == 'noscript') {
return;
}
writer.end(name);
}
}, new tinymce.html.Schema({})).parse(html);
return writer.getContent();
}
function updateHtml(html, data, updateAll) {
var writer = new tinymce.html.Writer();
var sourceCount = 0, hasImage;
function setAttributes(attrs, updatedAttrs) {
var name, i, value, attr;
for (name in updatedAttrs) {
value = "" + updatedAttrs[name];
if (attrs.map[name]) {
i = attrs.length;
while (i--) {
attr = attrs[i];
if (attr.name == name) {
if (value) {
attrs.map[name] = value;
attr.value = value;
} else {
delete attrs.map[name];
attrs.splice(i, 1);
}
}
}
} else if (value) {
attrs.push({
name: name,
value: value
});
attrs.map[name] = value;
}
}
}
new tinymce.html.SaxParser({
validate: false,
allow_conditional_comments: true,
special: 'script,noscript',
comment: function(text) {
writer.comment(text);
},
cdata: function(text) {
writer.cdata(text);
},
text: function(text, raw) {
writer.text(text, raw);
},
start: function(name, attrs, empty) {
switch (name) {
case "video":
case "object":
case "embed":
case "img":
case "iframe":
setAttributes(attrs, {
width: data.width,
height: data.height
});
break;
}
if (updateAll) {
switch (name) {
case "video":
setAttributes(attrs, {
poster: data.poster,
src: ""
});
if (data.source2) {
setAttributes(attrs, {
src: ""
});
}
break;
case "iframe":
setAttributes(attrs, {
src: data.source1
});
break;
case "source":
sourceCount++;
if (sourceCount <= 2) {
setAttributes(attrs, {
src: data["source" + sourceCount],
type: data["source" + sourceCount + "mime"]
});
if (!data["source" + sourceCount]) {
return;
}
}
break;
case "img":
if (!data.poster) {
return;
}
hasImage = true;
break;
}
}
writer.start(name, attrs, empty);
},
end: function(name) {
if (name == "video" && updateAll) {
for (var index = 1; index <= 2; index++) {
if (data["source" + index]) {
var attrs = [];
attrs.map = {};
if (sourceCount < index) {
setAttributes(attrs, {
src: data["source" + index],
type: data["source" + index + "mime"]
});
writer.start("source", attrs, true);
}
}
}
}
if (data.poster && name == "object" && updateAll && !hasImage) {
var imgAttrs = [];
imgAttrs.map = {};
setAttributes(imgAttrs, {
src: data.poster,
width: data.width,
height: data.height
});
writer.start("img", imgAttrs, true);
}
writer.end(name);
}
}, new tinymce.html.Schema({})).parse(html);
return writer.getContent();
}
editor.on('ResolveName', function(e) {
var name;
if (e.target.nodeType == 1 && (name = e.target.getAttribute("data-mce-object"))) {
e.name = name;
}
});
editor.on('preInit', function() {
// Make sure that any messy HTML is retained inside these
var specialElements = editor.schema.getSpecialElements();
tinymce.each('video audio iframe object'.split(' '), function(name) {
specialElements[name] = new RegExp('<\/' + name + '[^>]*>', 'gi');
});
// Allow elements
//editor.schema.addValidElements('object[id|style|width|height|classid|codebase|*],embed[id|style|width|height|type|src|*],video[*],audio[*]');
// Set allowFullscreen attribs as boolean
var boolAttrs = editor.schema.getBoolAttrs();
tinymce.each('webkitallowfullscreen mozallowfullscreen allowfullscreen'.split(' '), function(name) {
boolAttrs[name] = {};
});
// Converts iframe, video etc into placeholder images
editor.parser.addNodeFilter('iframe,video,audio,object,embed,script', function(nodes, name) {
var i = nodes.length, ai, node, placeHolder, attrName, attrValue, attribs, innerHtml;
var videoScript;
while (i--) {
node = nodes[i];
if (!node.parent) {
continue;
}
if (node.name == 'script') {
videoScript = getVideoScriptMatch(node.attr('src'));
if (!videoScript) {
continue;
}
}
placeHolder = new tinymce.html.Node('img', 1);
placeHolder.shortEnded = true;
if (videoScript) {
if (videoScript.width) {
node.attr('width', videoScript.width.toString());
}
if (videoScript.height) {
node.attr('height', videoScript.height.toString());
}
}
// Prefix all attributes except width, height and style since we
// will add these to the placeholder
attribs = node.attributes;
ai = attribs.length;
while (ai--) {
attrName = attribs[ai].name;
attrValue = attribs[ai].value;
if (attrName !== "width" && attrName !== "height" && attrName !== "style") {
if (attrName == "data" || attrName == "src") {
attrValue = editor.convertURL(attrValue, attrName);
}
placeHolder.attr('data-mce-p-' + attrName, attrValue);
}
}
// Place the inner HTML contents inside an escaped attribute
// This enables us to copy/paste the fake object
innerHtml = node.firstChild && node.firstChild.value;
if (innerHtml) {
placeHolder.attr("data-mce-html", escape(innerHtml));
placeHolder.firstChild = null;
}
placeHolder.attr({
width: node.attr('width') || "300",
height: node.attr('height') || (name == "audio" ? "30" : "150"),
style: node.attr('style'),
src: tinymce.Env.transparentSrc,
"data-mce-object": name,
"class": "mce-object mce-object-" + name
});
node.replace(placeHolder);
}
});
// Replaces placeholder images with real elements for video, object, iframe etc
editor.serializer.addAttributeFilter('data-mce-object', function(nodes, name) {
var i = nodes.length, node, realElm, ai, attribs, innerHtml, innerNode, realElmName;
while (i--) {
node = nodes[i];
if (!node.parent) {
continue;
}
realElmName = node.attr(name);
realElm = new tinymce.html.Node(realElmName, 1);
// Add width/height to everything but audio
if (realElmName != "audio" && realElmName != "script") {
realElm.attr({
width: node.attr('width'),
height: node.attr('height')
});
}
realElm.attr({
style: node.attr('style')
});
// Unprefix all placeholder attributes
attribs = node.attributes;
ai = attribs.length;
while (ai--) {
var attrName = attribs[ai].name;
if (attrName.indexOf('data-mce-p-') === 0) {
realElm.attr(attrName.substr(11), attribs[ai].value);
}
}
if (realElmName == "script") {
realElm.attr('type', 'text/javascript');
}
// Inject innerhtml
innerHtml = node.attr('data-mce-html');
if (innerHtml) {
innerNode = new tinymce.html.Node('#text', 3);
innerNode.raw = true;
innerNode.value = sanitize(unescape(innerHtml));
realElm.append(innerNode);
}
node.replace(realElm);
}
});
});
editor.on('ObjectSelected', function(e) {
var objectType = e.target.getAttribute('data-mce-object');
if (objectType == "audio" || objectType == "script") {
e.preventDefault();
}
});
editor.on('objectResized', function(e) {
var target = e.target, html;
if (target.getAttribute('data-mce-object')) {
html = target.getAttribute('data-mce-html');
if (html) {
html = unescape(html);
target.setAttribute('data-mce-html', escape(
updateHtml(html, {
width: e.width,
height: e.height
})
));
}
}
});
editor.addButton('media', {
tooltip: 'Insert/edit video',
onclick: showDialog,
stateSelector: ['img[data-mce-object=video]', 'img[data-mce-object=iframe]']
});
editor.addMenuItem('media', {
icon: 'media',
text: 'Insert video',
onclick: showDialog,
context: 'insert',
prependToContext: true
});
});

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,53 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('nonbreaking', function(editor) {
var setting = editor.getParam('nonbreaking_force_tab');
editor.addCommand('mceNonBreaking', function() {
editor.insertContent(
(editor.plugins.visualchars && editor.plugins.visualchars.state) ?
'<span class="mce-nbsp">&nbsp;</span>' : '&nbsp;'
);
editor.dom.setAttrib(editor.dom.select('span.mce-nbsp'), 'data-mce-bogus', '1');
});
editor.addButton('nonbreaking', {
title: 'Nonbreaking space',
cmd: 'mceNonBreaking'
});
editor.addMenuItem('nonbreaking', {
text: 'Nonbreaking space',
cmd: 'mceNonBreaking',
context: 'insert'
});
if (setting) {
var spaces = +setting > 1 ? +setting : 3; // defaults to 3 spaces if setting is true (or 1)
editor.on('keydown', function(e) {
if (e.keyCode == 9) {
if (e.shiftKey) {
return;
}
e.preventDefault();
for (var i = 0; i < spaces; i++) {
editor.execCommand('mceNonBreaking');
}
}
});
}
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("nonbreaking",function(a){var b=a.getParam("nonbreaking_force_tab");if(a.addCommand("mceNonBreaking",function(){a.insertContent(a.plugins.visualchars&&a.plugins.visualchars.state?'<span class="mce-nbsp">&nbsp;</span>':"&nbsp;"),a.dom.setAttrib(a.dom.select("span.mce-nbsp"),"data-mce-bogus","1")}),a.addButton("nonbreaking",{title:"Nonbreaking space",cmd:"mceNonBreaking"}),a.addMenuItem("nonbreaking",{text:"Nonbreaking space",cmd:"mceNonBreaking",context:"insert"}),b){var c=+b>1?+b:3;a.on("keydown",function(b){if(9==b.keyCode){if(b.shiftKey)return;b.preventDefault();for(var d=0;c>d;d++)a.execCommand("mceNonBreaking")}})}});

View File

@ -0,0 +1,540 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*jshint loopfunc:true */
/*eslint no-loop-func:0 */
/*global tinymce:true */
tinymce.PluginManager.add('noneditable', function(editor) {
var TreeWalker = tinymce.dom.TreeWalker;
var externalName = 'contenteditable', internalName = 'data-mce-' + externalName;
var VK = tinymce.util.VK;
// Returns the content editable state of a node "true/false" or null
function getContentEditable(node) {
var contentEditable;
// Ignore non elements
if (node.nodeType === 1) {
// Check for fake content editable
contentEditable = node.getAttribute(internalName);
if (contentEditable && contentEditable !== "inherit") {
return contentEditable;
}
// Check for real content editable
contentEditable = node.contentEditable;
if (contentEditable !== "inherit") {
return contentEditable;
}
}
return null;
}
// Returns the noneditable parent or null if there is a editable before it or if it wasn't found
function getNonEditableParent(node) {
var state;
while (node) {
state = getContentEditable(node);
if (state) {
return state === "false" ? node : null;
}
node = node.parentNode;
}
}
function handleContentEditableSelection() {
var dom = editor.dom, selection = editor.selection, caretContainerId = 'mce_noneditablecaret', invisibleChar = '\uFEFF';
// Get caret container parent for the specified node
function getParentCaretContainer(node) {
while (node) {
if (node.id === caretContainerId) {
return node;
}
node = node.parentNode;
}
}
// Finds the first text node in the specified node
function findFirstTextNode(node) {
var walker;
if (node) {
walker = new TreeWalker(node, node);
for (node = walker.current(); node; node = walker.next()) {
if (node.nodeType === 3) {
return node;
}
}
}
}
// Insert caret container before/after target or expand selection to include block
function insertCaretContainerOrExpandToBlock(target, before) {
var caretContainer, rng;
// Select block
if (getContentEditable(target) === "false") {
if (dom.isBlock(target)) {
selection.select(target);
return;
}
}
rng = dom.createRng();
if (getContentEditable(target) === "true") {
if (!target.firstChild) {
target.appendChild(editor.getDoc().createTextNode('\u00a0'));
}
target = target.firstChild;
before = true;
}
/*
caretContainer = dom.create('span', {
id: caretContainerId,
'data-mce-bogus': true,
style:'border: 1px solid red'
}, invisibleChar);
*/
caretContainer = dom.create('span', {id: caretContainerId, 'data-mce-bogus': true}, invisibleChar);
if (before) {
target.parentNode.insertBefore(caretContainer, target);
} else {
dom.insertAfter(caretContainer, target);
}
rng.setStart(caretContainer.firstChild, 1);
rng.collapse(true);
selection.setRng(rng);
return caretContainer;
}
// Removes any caret container except the one we might be in
function removeCaretContainer(caretContainer) {
var rng, child, currentCaretContainer, lastContainer;
if (caretContainer) {
rng = selection.getRng(true);
rng.setStartBefore(caretContainer);
rng.setEndBefore(caretContainer);
child = findFirstTextNode(caretContainer);
if (child && child.nodeValue.charAt(0) == invisibleChar) {
child = child.deleteData(0, 1);
}
dom.remove(caretContainer, true);
selection.setRng(rng);
} else {
currentCaretContainer = getParentCaretContainer(selection.getStart());
while ((caretContainer = dom.get(caretContainerId)) && caretContainer !== lastContainer) {
if (currentCaretContainer !== caretContainer) {
child = findFirstTextNode(caretContainer);
if (child && child.nodeValue.charAt(0) == invisibleChar) {
child = child.deleteData(0, 1);
}
dom.remove(caretContainer, true);
}
lastContainer = caretContainer;
}
}
}
// Modifies the selection to include contentEditable false elements or insert caret containers
function moveSelection() {
var nonEditableStart, nonEditableEnd, isCollapsed, rng, element;
// Checks if there is any contents to the left/right side of caret returns the noneditable element or
// any editable element if it finds one inside
function hasSideContent(element, left) {
var container, offset, walker, node, len;
container = rng.startContainer;
offset = rng.startOffset;
// If endpoint is in middle of text node then expand to beginning/end of element
if (container.nodeType == 3) {
len = container.nodeValue.length;
if ((offset > 0 && offset < len) || (left ? offset == len : offset === 0)) {
return;
}
} else {
// Can we resolve the node by index
if (offset < container.childNodes.length) {
// Browser represents caret position as the offset at the start of an element. When moving right
// this is the element we are moving into so we consider our container to be child node at offset-1
var pos = !left && offset > 0 ? offset - 1 : offset;
container = container.childNodes[pos];
if (container.hasChildNodes()) {
container = container.firstChild;
}
} else {
// If not then the caret is at the last position in it's container and the caret container
// should be inserted after the noneditable element
return !left ? element : null;
}
}
// Walk left/right to look for contents
walker = new TreeWalker(container, element);
while ((node = walker[left ? 'prev' : 'next']())) {
if (node.nodeType === 3 && node.nodeValue.length > 0) {
return;
} else if (getContentEditable(node) === "true") {
// Found contentEditable=true element return this one to we can move the caret inside it
return node;
}
}
return element;
}
// Remove any existing caret containers
removeCaretContainer();
// Get noneditable start/end elements
isCollapsed = selection.isCollapsed();
nonEditableStart = getNonEditableParent(selection.getStart());
nonEditableEnd = getNonEditableParent(selection.getEnd());
// Is any fo the range endpoints noneditable
if (nonEditableStart || nonEditableEnd) {
rng = selection.getRng(true);
// If it's a caret selection then look left/right to see if we need to move the caret out side or expand
if (isCollapsed) {
nonEditableStart = nonEditableStart || nonEditableEnd;
if ((element = hasSideContent(nonEditableStart, true))) {
// We have no contents to the left of the caret then insert a caret container before the noneditable element
insertCaretContainerOrExpandToBlock(element, true);
} else if ((element = hasSideContent(nonEditableStart, false))) {
// We have no contents to the right of the caret then insert a caret container after the noneditable element
insertCaretContainerOrExpandToBlock(element, false);
} else {
// We are in the middle of a noneditable so expand to select it
selection.select(nonEditableStart);
}
} else {
rng = selection.getRng(true);
// Expand selection to include start non editable element
if (nonEditableStart) {
rng.setStartBefore(nonEditableStart);
}
// Expand selection to include end non editable element
if (nonEditableEnd) {
rng.setEndAfter(nonEditableEnd);
}
selection.setRng(rng);
}
}
}
function handleKey(e) {
var keyCode = e.keyCode, nonEditableParent, caretContainer, startElement, endElement;
function getNonEmptyTextNodeSibling(node, prev) {
while ((node = node[prev ? 'previousSibling' : 'nextSibling'])) {
if (node.nodeType !== 3 || node.nodeValue.length > 0) {
return node;
}
}
}
function positionCaretOnElement(element, start) {
selection.select(element);
selection.collapse(start);
}
function canDelete(backspace) {
var rng, container, offset, nonEditableParent;
function removeNodeIfNotParent(node) {
var parent = container;
while (parent) {
if (parent === node) {
return;
}
parent = parent.parentNode;
}
dom.remove(node);
moveSelection();
}
function isNextPrevTreeNodeNonEditable() {
var node, walker, nonEmptyElements = editor.schema.getNonEmptyElements();
walker = new tinymce.dom.TreeWalker(container, editor.getBody());
while ((node = (backspace ? walker.prev() : walker.next()))) {
// Found IMG/INPUT etc
if (nonEmptyElements[node.nodeName.toLowerCase()]) {
break;
}
// Found text node with contents
if (node.nodeType === 3 && tinymce.trim(node.nodeValue).length > 0) {
break;
}
// Found non editable node
if (getContentEditable(node) === "false") {
removeNodeIfNotParent(node);
return true;
}
}
// Check if the content node is within a non editable parent
if (getNonEditableParent(node)) {
return true;
}
return false;
}
if (selection.isCollapsed()) {
rng = selection.getRng(true);
container = rng.startContainer;
offset = rng.startOffset;
container = getParentCaretContainer(container) || container;
// Is in noneditable parent
if ((nonEditableParent = getNonEditableParent(container))) {
removeNodeIfNotParent(nonEditableParent);
return false;
}
// Check if the caret is in the middle of a text node
if (container.nodeType == 3 && (backspace ? offset > 0 : offset < container.nodeValue.length)) {
return true;
}
// Resolve container index
if (container.nodeType == 1) {
container = container.childNodes[offset] || container;
}
// Check if previous or next tree node is non editable then block the event
if (isNextPrevTreeNodeNonEditable()) {
return false;
}
}
return true;
}
startElement = selection.getStart();
endElement = selection.getEnd();
// Disable all key presses in contentEditable=false except delete or backspace
nonEditableParent = getNonEditableParent(startElement) || getNonEditableParent(endElement);
if (nonEditableParent && (keyCode < 112 || keyCode > 124) && keyCode != VK.DELETE && keyCode != VK.BACKSPACE) {
// Is Ctrl+c, Ctrl+v or Ctrl+x then use default browser behavior
if ((tinymce.isMac ? e.metaKey : e.ctrlKey) && (keyCode == 67 || keyCode == 88 || keyCode == 86)) {
return;
}
e.preventDefault();
// Arrow left/right select the element and collapse left/right
if (keyCode == VK.LEFT || keyCode == VK.RIGHT) {
var left = keyCode == VK.LEFT;
// If a block element find previous or next element to position the caret
if (editor.dom.isBlock(nonEditableParent)) {
var targetElement = left ? nonEditableParent.previousSibling : nonEditableParent.nextSibling;
var walker = new TreeWalker(targetElement, targetElement);
var caretElement = left ? walker.prev() : walker.next();
positionCaretOnElement(caretElement, !left);
} else {
positionCaretOnElement(nonEditableParent, left);
}
}
} else {
// Is arrow left/right, backspace or delete
if (keyCode == VK.LEFT || keyCode == VK.RIGHT || keyCode == VK.BACKSPACE || keyCode == VK.DELETE) {
caretContainer = getParentCaretContainer(startElement);
if (caretContainer) {
// Arrow left or backspace
if (keyCode == VK.LEFT || keyCode == VK.BACKSPACE) {
nonEditableParent = getNonEmptyTextNodeSibling(caretContainer, true);
if (nonEditableParent && getContentEditable(nonEditableParent) === "false") {
e.preventDefault();
if (keyCode == VK.LEFT) {
positionCaretOnElement(nonEditableParent, true);
} else {
dom.remove(nonEditableParent);
return;
}
} else {
removeCaretContainer(caretContainer);
}
}
// Arrow right or delete
if (keyCode == VK.RIGHT || keyCode == VK.DELETE) {
nonEditableParent = getNonEmptyTextNodeSibling(caretContainer);
if (nonEditableParent && getContentEditable(nonEditableParent) === "false") {
e.preventDefault();
if (keyCode == VK.RIGHT) {
positionCaretOnElement(nonEditableParent, false);
} else {
dom.remove(nonEditableParent);
return;
}
} else {
removeCaretContainer(caretContainer);
}
}
}
if ((keyCode == VK.BACKSPACE || keyCode == VK.DELETE) && !canDelete(keyCode == VK.BACKSPACE)) {
e.preventDefault();
return false;
}
}
}
}
editor.on('mousedown', function(e) {
var node = editor.selection.getNode();
if (getContentEditable(node) === "false" && node == e.target) {
// Expand selection on mouse down we can't block the default event since it's used for drag/drop
moveSelection();
}
});
editor.on('mouseup keyup', moveSelection);
editor.on('keydown', handleKey);
}
var editClass, nonEditClass, nonEditableRegExps;
// Converts configured regexps to noneditable span items
function convertRegExpsToNonEditable(e) {
var i = nonEditableRegExps.length, content = e.content, cls = tinymce.trim(nonEditClass);
// Don't replace the variables when raw is used for example on undo/redo
if (e.format == "raw") {
return;
}
while (i--) {
content = content.replace(nonEditableRegExps[i], function(match) {
var args = arguments, index = args[args.length - 2];
// Is value inside an attribute then don't replace
if (index > 0 && content.charAt(index - 1) == '"') {
return match;
}
return (
'<span class="' + cls + '" data-mce-content="' + editor.dom.encode(args[0]) + '">' +
editor.dom.encode(typeof(args[1]) === "string" ? args[1] : args[0]) + '</span>'
);
});
}
e.content = content;
}
editClass = " " + tinymce.trim(editor.getParam("noneditable_editable_class", "mceEditable")) + " ";
nonEditClass = " " + tinymce.trim(editor.getParam("noneditable_noneditable_class", "mceNonEditable")) + " ";
// Setup noneditable regexps array
nonEditableRegExps = editor.getParam("noneditable_regexp");
if (nonEditableRegExps && !nonEditableRegExps.length) {
nonEditableRegExps = [nonEditableRegExps];
}
editor.on('PreInit', function() {
handleContentEditableSelection();
if (nonEditableRegExps) {
editor.on('BeforeSetContent', convertRegExpsToNonEditable);
}
// Apply contentEditable true/false on elements with the noneditable/editable classes
editor.parser.addAttributeFilter('class', function(nodes) {
var i = nodes.length, className, node;
while (i--) {
node = nodes[i];
className = " " + node.attr("class") + " ";
if (className.indexOf(editClass) !== -1) {
node.attr(internalName, "true");
} else if (className.indexOf(nonEditClass) !== -1) {
node.attr(internalName, "false");
}
}
});
// Remove internal name
editor.serializer.addAttributeFilter(internalName, function(nodes) {
var i = nodes.length, node;
while (i--) {
node = nodes[i];
if (nonEditableRegExps && node.attr('data-mce-content')) {
node.name = "#text";
node.type = 3;
node.raw = true;
node.value = node.attr('data-mce-content');
} else {
node.attr(externalName, null);
node.attr(internalName, null);
}
}
});
// Convert external name into internal name
editor.parser.addAttributeFilter(externalName, function(nodes) {
var i = nodes.length, node;
while (i--) {
node = nodes[i];
node.attr(internalName, node.attr(externalName));
node.attr(externalName, null);
}
});
});
editor.on('drop', function(e) {
if (getNonEditableParent(e.target)) {
e.preventDefault();
}
});
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("noneditable",function(a){function b(a){var b;if(1===a.nodeType){if(b=a.getAttribute(k),b&&"inherit"!==b)return b;if(b=a.contentEditable,"inherit"!==b)return b}return null}function c(a){for(var c;a;){if(c=b(a))return"false"===c?a:null;a=a.parentNode}}function d(){function d(a){for(;a;){if(a.id===n)return a;a=a.parentNode}}function e(a){var b;if(a)for(b=new i(a,a),a=b.current();a;a=b.next())if(3===a.nodeType)return a}function f(c,d){var e,f;return"false"===b(c)&&k.isBlock(c)?void m.select(c):(f=k.createRng(),"true"===b(c)&&(c.firstChild||c.appendChild(a.getDoc().createTextNode("\xa0")),c=c.firstChild,d=!0),e=k.create("span",{id:n,"data-mce-bogus":!0},o),d?c.parentNode.insertBefore(e,c):k.insertAfter(e,c),f.setStart(e.firstChild,1),f.collapse(!0),m.setRng(f),e)}function g(a){var b,c,f,g;if(a)b=m.getRng(!0),b.setStartBefore(a),b.setEndBefore(a),c=e(a),c&&c.nodeValue.charAt(0)==o&&(c=c.deleteData(0,1)),k.remove(a,!0),m.setRng(b);else for(f=d(m.getStart());(a=k.get(n))&&a!==g;)f!==a&&(c=e(a),c&&c.nodeValue.charAt(0)==o&&(c=c.deleteData(0,1)),k.remove(a,!0)),g=a}function h(){function a(a,c){var d,e,f,g,h;if(d=j.startContainer,e=j.startOffset,3==d.nodeType){if(h=d.nodeValue.length,e>0&&h>e||(c?e==h:0===e))return}else{if(!(e<d.childNodes.length))return c?null:a;var k=!c&&e>0?e-1:e;d=d.childNodes[k],d.hasChildNodes()&&(d=d.firstChild)}for(f=new i(d,a);g=f[c?"prev":"next"]();){if(3===g.nodeType&&g.nodeValue.length>0)return;if("true"===b(g))return g}return a}var d,e,h,j,k;g(),h=m.isCollapsed(),d=c(m.getStart()),e=c(m.getEnd()),(d||e)&&(j=m.getRng(!0),h?(d=d||e,(k=a(d,!0))?f(k,!0):(k=a(d,!1))?f(k,!1):m.select(d)):(j=m.getRng(!0),d&&j.setStartBefore(d),e&&j.setEndAfter(e),m.setRng(j)))}function j(e){function f(a,b){for(;a=a[b?"previousSibling":"nextSibling"];)if(3!==a.nodeType||a.nodeValue.length>0)return a}function j(a,b){m.select(a),m.collapse(b)}function n(e){function f(a){for(var b=j;b;){if(b===a)return;b=b.parentNode}k.remove(a),h()}function g(){var d,g,h=a.schema.getNonEmptyElements();for(g=new tinymce.dom.TreeWalker(j,a.getBody());(d=e?g.prev():g.next())&&!h[d.nodeName.toLowerCase()]&&!(3===d.nodeType&&tinymce.trim(d.nodeValue).length>0);)if("false"===b(d))return f(d),!0;return c(d)?!0:!1}var i,j,l,n;if(m.isCollapsed()){if(i=m.getRng(!0),j=i.startContainer,l=i.startOffset,j=d(j)||j,n=c(j))return f(n),!1;if(3==j.nodeType&&(e?l>0:l<j.nodeValue.length))return!0;if(1==j.nodeType&&(j=j.childNodes[l]||j),g())return!1}return!0}var o,p,q,r,s=e.keyCode;if(q=m.getStart(),r=m.getEnd(),o=c(q)||c(r),o&&(112>s||s>124)&&s!=l.DELETE&&s!=l.BACKSPACE){if((tinymce.isMac?e.metaKey:e.ctrlKey)&&(67==s||88==s||86==s))return;if(e.preventDefault(),s==l.LEFT||s==l.RIGHT){var t=s==l.LEFT;if(a.dom.isBlock(o)){var u=t?o.previousSibling:o.nextSibling,v=new i(u,u),w=t?v.prev():v.next();j(w,!t)}else j(o,t)}}else if(s==l.LEFT||s==l.RIGHT||s==l.BACKSPACE||s==l.DELETE){if(p=d(q)){if(s==l.LEFT||s==l.BACKSPACE)if(o=f(p,!0),o&&"false"===b(o)){if(e.preventDefault(),s!=l.LEFT)return void k.remove(o);j(o,!0)}else g(p);if(s==l.RIGHT||s==l.DELETE)if(o=f(p),o&&"false"===b(o)){if(e.preventDefault(),s!=l.RIGHT)return void k.remove(o);j(o,!1)}else g(p)}if((s==l.BACKSPACE||s==l.DELETE)&&!n(s==l.BACKSPACE))return e.preventDefault(),!1}}var k=a.dom,m=a.selection,n="mce_noneditablecaret",o="\ufeff";a.on("mousedown",function(c){var d=a.selection.getNode();"false"===b(d)&&d==c.target&&h()}),a.on("mouseup keyup",h),a.on("keydown",j)}function e(b){var c=h.length,d=b.content,e=tinymce.trim(g);if("raw"!=b.format){for(;c--;)d=d.replace(h[c],function(b){var c=arguments,f=c[c.length-2];return f>0&&'"'==d.charAt(f-1)?b:'<span class="'+e+'" data-mce-content="'+a.dom.encode(c[0])+'">'+a.dom.encode("string"==typeof c[1]?c[1]:c[0])+"</span>"});b.content=d}}var f,g,h,i=tinymce.dom.TreeWalker,j="contenteditable",k="data-mce-"+j,l=tinymce.util.VK;f=" "+tinymce.trim(a.getParam("noneditable_editable_class","mceEditable"))+" ",g=" "+tinymce.trim(a.getParam("noneditable_noneditable_class","mceNonEditable"))+" ",h=a.getParam("noneditable_regexp"),h&&!h.length&&(h=[h]),a.on("PreInit",function(){d(),h&&a.on("BeforeSetContent",e),a.parser.addAttributeFilter("class",function(a){for(var b,c,d=a.length;d--;)c=a[d],b=" "+c.attr("class")+" ",-1!==b.indexOf(f)?c.attr(k,"true"):-1!==b.indexOf(g)&&c.attr(k,"false")}),a.serializer.addAttributeFilter(k,function(a){for(var b,c=a.length;c--;)b=a[c],h&&b.attr("data-mce-content")?(b.name="#text",b.type=3,b.raw=!0,b.value=b.attr("data-mce-content")):(b.attr(j,null),b.attr(k,null))}),a.parser.addAttributeFilter(j,function(a){for(var b,c=a.length;c--;)b=a[c],b.attr(k,b.attr(j)),b.attr(j,null)})}),a.on("drop",function(a){c(a.target)&&a.preventDefault()})});

View File

@ -0,0 +1,88 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('pagebreak', function(editor) {
var pageBreakClass = 'mce-pagebreak', separatorHtml = editor.getParam('pagebreak_separator', '<!-- pagebreak -->');
var pageBreakSeparatorRegExp = new RegExp(separatorHtml.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g, function(a) {
return '\\' + a;
}), 'gi');
var pageBreakPlaceHolderHtml = '<img src="' + tinymce.Env.transparentSrc + '" class="' +
pageBreakClass + '" data-mce-resize="false" />';
// Register commands
editor.addCommand('mcePageBreak', function() {
if (editor.settings.pagebreak_split_block) {
editor.insertContent('<p>' + pageBreakPlaceHolderHtml + '</p>');
} else {
editor.insertContent(pageBreakPlaceHolderHtml);
}
});
// Register buttons
editor.addButton('pagebreak', {
title: 'Page break',
cmd: 'mcePageBreak'
});
editor.addMenuItem('pagebreak', {
text: 'Page break',
icon: 'pagebreak',
cmd: 'mcePageBreak',
context: 'insert'
});
editor.on('ResolveName', function(e) {
if (e.target.nodeName == 'IMG' && editor.dom.hasClass(e.target, pageBreakClass)) {
e.name = 'pagebreak';
}
});
editor.on('click', function(e) {
e = e.target;
if (e.nodeName === 'IMG' && editor.dom.hasClass(e, pageBreakClass)) {
editor.selection.select(e);
}
});
editor.on('BeforeSetContent', function(e) {
e.content = e.content.replace(pageBreakSeparatorRegExp, pageBreakPlaceHolderHtml);
});
editor.on('PreInit', function() {
editor.serializer.addNodeFilter('img', function(nodes) {
var i = nodes.length, node, className;
while (i--) {
node = nodes[i];
className = node.attr('class');
if (className && className.indexOf('mce-pagebreak') !== -1) {
// Replace parent block node if pagebreak_split_block is enabled
var parentNode = node.parent;
if (editor.schema.getBlockElements()[parentNode.name] && editor.settings.pagebreak_split_block) {
parentNode.type = 3;
parentNode.value = separatorHtml;
parentNode.raw = true;
node.remove();
continue;
}
node.type = 3;
node.value = separatorHtml;
node.raw = true;
}
}
});
});
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("pagebreak",function(a){var b="mce-pagebreak",c=a.getParam("pagebreak_separator","<!-- pagebreak -->"),d=new RegExp(c.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,function(a){return"\\"+a}),"gi"),e='<img src="'+tinymce.Env.transparentSrc+'" class="'+b+'" data-mce-resize="false" />';a.addCommand("mcePageBreak",function(){a.insertContent(a.settings.pagebreak_split_block?"<p>"+e+"</p>":e)}),a.addButton("pagebreak",{title:"Page break",cmd:"mcePageBreak"}),a.addMenuItem("pagebreak",{text:"Page break",icon:"pagebreak",cmd:"mcePageBreak",context:"insert"}),a.on("ResolveName",function(c){"IMG"==c.target.nodeName&&a.dom.hasClass(c.target,b)&&(c.name="pagebreak")}),a.on("click",function(c){c=c.target,"IMG"===c.nodeName&&a.dom.hasClass(c,b)&&a.selection.select(c)}),a.on("BeforeSetContent",function(a){a.content=a.content.replace(d,e)}),a.on("PreInit",function(){a.serializer.addNodeFilter("img",function(b){for(var d,e,f=b.length;f--;)if(d=b[f],e=d.attr("class"),e&&-1!==e.indexOf("mce-pagebreak")){var g=d.parent;if(a.schema.getBlockElements()[g.name]&&a.settings.pagebreak_split_block){g.type=3,g.value=c,g.raw=!0,d.remove();continue}d.type=3,d.value=c,d.raw=!0}})})});

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,88 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('preview', function(editor) {
var settings = editor.settings, sandbox = !tinymce.Env.ie;
editor.addCommand('mcePreview', function() {
editor.windowManager.open({
title: 'Preview',
width : parseInt(editor.getParam("plugin_preview_width", "650"), 10),
height : parseInt(editor.getParam("plugin_preview_height", "500"), 10),
html: '<iframe src="javascript:\'\'" frameborder="0"' + (sandbox ? ' sandbox="allow-scripts"' : '') + '></iframe>',
buttons: {
text: 'Close',
onclick: function() {
this.parent().parent().close();
}
},
onPostRender: function() {
var previewHtml, headHtml = '';
headHtml += '<base href="' + editor.documentBaseURI.getURI() + '">';
tinymce.each(editor.contentCSS, function(url) {
headHtml += '<link type="text/css" rel="stylesheet" href="' + editor.documentBaseURI.toAbsolute(url) + '">';
});
var bodyId = settings.body_id || 'tinymce';
if (bodyId.indexOf('=') != -1) {
bodyId = editor.getParam('body_id', '', 'hash');
bodyId = bodyId[editor.id] || bodyId;
}
var bodyClass = settings.body_class || '';
if (bodyClass.indexOf('=') != -1) {
bodyClass = editor.getParam('body_class', '', 'hash');
bodyClass = bodyClass[editor.id] || '';
}
var dirAttr = editor.settings.directionality ? ' dir="' + editor.settings.directionality + '"' : '';
previewHtml = (
'<!DOCTYPE html>' +
'<html>' +
'<head>' +
headHtml +
'</head>' +
'<body id="' + bodyId + '" class="mce-content-body ' + bodyClass + '"' + dirAttr + '>' +
editor.getContent() +
'</body>' +
'</html>'
);
if (!sandbox) {
// IE 6-11 doesn't support data uris on iframes
// so I guess they will have to be less secure since we can't sandbox on those
// TODO: Use sandbox if future versions of IE supports iframes with data: uris.
var doc = this.getEl('body').firstChild.contentWindow.document;
doc.open();
doc.write(previewHtml);
doc.close();
} else {
this.getEl('body').firstChild.src = 'data:text/html;charset=utf-8,' + encodeURIComponent(previewHtml);
}
}
});
});
editor.addButton('preview', {
title : 'Preview',
cmd : 'mcePreview'
});
editor.addMenuItem('preview', {
text : 'Preview',
cmd : 'mcePreview',
context: 'view'
});
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("preview",function(a){var b=a.settings,c=!tinymce.Env.ie;a.addCommand("mcePreview",function(){a.windowManager.open({title:"Preview",width:parseInt(a.getParam("plugin_preview_width","650"),10),height:parseInt(a.getParam("plugin_preview_height","500"),10),html:'<iframe src="javascript:\'\'" frameborder="0"'+(c?' sandbox="allow-scripts"':"")+"></iframe>",buttons:{text:"Close",onclick:function(){this.parent().parent().close()}},onPostRender:function(){var d,e="";e+='<base href="'+a.documentBaseURI.getURI()+'">',tinymce.each(a.contentCSS,function(b){e+='<link type="text/css" rel="stylesheet" href="'+a.documentBaseURI.toAbsolute(b)+'">'});var f=b.body_id||"tinymce";-1!=f.indexOf("=")&&(f=a.getParam("body_id","","hash"),f=f[a.id]||f);var g=b.body_class||"";-1!=g.indexOf("=")&&(g=a.getParam("body_class","","hash"),g=g[a.id]||"");var h=a.settings.directionality?' dir="'+a.settings.directionality+'"':"";if(d="<!DOCTYPE html><html><head>"+e+'</head><body id="'+f+'" class="mce-content-body '+g+'"'+h+">"+a.getContent()+"</body></html>",c)this.getEl("body").firstChild.src="data:text/html;charset=utf-8,"+encodeURIComponent(d);else{var i=this.getEl("body").firstChild.contentWindow.document;i.open(),i.write(d),i.close()}}})}),a.addButton("preview",{title:"Preview",cmd:"mcePreview"}),a.addMenuItem("preview",{text:"Preview",cmd:"mcePreview",context:"view"})});

View File

@ -0,0 +1,32 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('print', function(editor) {
editor.addCommand('mcePrint', function() {
editor.getWin().print();
});
editor.addButton('print', {
title: 'Print',
cmd: 'mcePrint'
});
editor.addShortcut('Ctrl+P', '', 'mcePrint');
editor.addMenuItem('print', {
text: 'Print',
cmd: 'mcePrint',
icon: 'print',
shortcut: 'Ctrl+P',
context: 'file'
});
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("print",function(a){a.addCommand("mcePrint",function(){a.getWin().print()}),a.addButton("print",{title:"Print",cmd:"mcePrint"}),a.addShortcut("Ctrl+P","","mcePrint"),a.addMenuItem("print",{text:"Print",cmd:"mcePrint",icon:"print",shortcut:"Ctrl+P",context:"file"})});

View File

@ -0,0 +1,94 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('save', function(editor) {
function save() {
var formObj;
formObj = tinymce.DOM.getParent(editor.id, 'form');
if (editor.getParam("save_enablewhendirty", true) && !editor.isDirty()) {
return;
}
tinymce.triggerSave();
// Use callback instead
if (editor.getParam("save_onsavecallback")) {
if (editor.execCallback('save_onsavecallback', editor)) {
editor.startContent = tinymce.trim(editor.getContent({format: 'raw'}));
editor.nodeChanged();
}
return;
}
if (formObj) {
editor.isNotDirty = true;
if (!formObj.onsubmit || formObj.onsubmit()) {
if (typeof(formObj.submit) == "function") {
formObj.submit();
} else {
editor.windowManager.alert("Error: Form submit field collision.");
}
}
editor.nodeChanged();
} else {
editor.windowManager.alert("Error: No form element found.");
}
}
function cancel() {
var h = tinymce.trim(editor.startContent);
// Use callback instead
if (editor.getParam("save_oncancelcallback")) {
editor.execCallback('save_oncancelcallback', editor);
return;
}
editor.setContent(h);
editor.undoManager.clear();
editor.nodeChanged();
}
function stateToggle() {
var self = this;
editor.on('nodeChange', function() {
self.disabled(editor.getParam("save_enablewhendirty", true) && !editor.isDirty());
});
}
editor.addCommand('mceSave', save);
editor.addCommand('mceCancel', cancel);
editor.addButton('save', {
icon: 'save',
text: 'Save',
cmd: 'mceSave',
disabled: true,
onPostRender: stateToggle
});
editor.addButton('cancel', {
text: 'Cancel',
icon: false,
cmd: 'mceCancel',
disabled: true,
onPostRender: stateToggle
});
editor.addShortcut('ctrl+s', '', 'mceSave');
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("save",function(a){function b(){var b;return b=tinymce.DOM.getParent(a.id,"form"),!a.getParam("save_enablewhendirty",!0)||a.isDirty()?(tinymce.triggerSave(),a.getParam("save_onsavecallback")?void(a.execCallback("save_onsavecallback",a)&&(a.startContent=tinymce.trim(a.getContent({format:"raw"})),a.nodeChanged())):void(b?(a.isNotDirty=!0,(!b.onsubmit||b.onsubmit())&&("function"==typeof b.submit?b.submit():a.windowManager.alert("Error: Form submit field collision.")),a.nodeChanged()):a.windowManager.alert("Error: No form element found."))):void 0}function c(){var b=tinymce.trim(a.startContent);return a.getParam("save_oncancelcallback")?void a.execCallback("save_oncancelcallback",a):(a.setContent(b),a.undoManager.clear(),void a.nodeChanged())}function d(){var b=this;a.on("nodeChange",function(){b.disabled(a.getParam("save_enablewhendirty",!0)&&!a.isDirty())})}a.addCommand("mceSave",b),a.addCommand("mceCancel",c),a.addButton("save",{icon:"save",text:"Save",cmd:"mceSave",disabled:!0,onPostRender:d}),a.addButton("cancel",{text:"Cancel",icon:!1,cmd:"mceCancel",disabled:!0,onPostRender:d}),a.addShortcut("ctrl+s","","mceSave")});

View File

@ -0,0 +1,594 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*jshint smarttabs:true, undef:true, unused:true, latedef:true, curly:true, bitwise:true */
/*eslint no-labels:0, no-constant-condition: 0 */
/*global tinymce:true */
(function() {
// Based on work developed by: James Padolsey http://james.padolsey.com
// released under UNLICENSE that is compatible with LGPL
// TODO: Handle contentEditable edgecase:
// <p>text<span contentEditable="false">text<span contentEditable="true">text</span>text</span>text</p>
function findAndReplaceDOMText(regex, node, replacementNode, captureGroup, schema) {
var m, matches = [], text, count = 0, doc;
var blockElementsMap, hiddenTextElementsMap, shortEndedElementsMap;
doc = node.ownerDocument;
blockElementsMap = schema.getBlockElements(); // H1-H6, P, TD etc
hiddenTextElementsMap = schema.getWhiteSpaceElements(); // TEXTAREA, PRE, STYLE, SCRIPT
shortEndedElementsMap = schema.getShortEndedElements(); // BR, IMG, INPUT
function getMatchIndexes(m, captureGroup) {
captureGroup = captureGroup || 0;
if (!m[0]) {
throw 'findAndReplaceDOMText cannot handle zero-length matches';
}
var index = m.index;
if (captureGroup > 0) {
var cg = m[captureGroup];
if (!cg) {
throw 'Invalid capture group';
}
index += m[0].indexOf(cg);
m[0] = cg;
}
return [index, index + m[0].length, [m[0]]];
}
function getText(node) {
var txt;
if (node.nodeType === 3) {
return node.data;
}
if (hiddenTextElementsMap[node.nodeName] && !blockElementsMap[node.nodeName]) {
return '';
}
txt = '';
if (blockElementsMap[node.nodeName] || shortEndedElementsMap[node.nodeName]) {
txt += '\n';
}
if ((node = node.firstChild)) {
do {
txt += getText(node);
} while ((node = node.nextSibling));
}
return txt;
}
function stepThroughMatches(node, matches, replaceFn) {
var startNode, endNode, startNodeIndex,
endNodeIndex, innerNodes = [], atIndex = 0, curNode = node,
matchLocation = matches.shift(), matchIndex = 0;
out: while (true) {
if (blockElementsMap[curNode.nodeName] || shortEndedElementsMap[curNode.nodeName]) {
atIndex++;
}
if (curNode.nodeType === 3) {
if (!endNode && curNode.length + atIndex >= matchLocation[1]) {
// We've found the ending
endNode = curNode;
endNodeIndex = matchLocation[1] - atIndex;
} else if (startNode) {
// Intersecting node
innerNodes.push(curNode);
}
if (!startNode && curNode.length + atIndex > matchLocation[0]) {
// We've found the match start
startNode = curNode;
startNodeIndex = matchLocation[0] - atIndex;
}
atIndex += curNode.length;
}
if (startNode && endNode) {
curNode = replaceFn({
startNode: startNode,
startNodeIndex: startNodeIndex,
endNode: endNode,
endNodeIndex: endNodeIndex,
innerNodes: innerNodes,
match: matchLocation[2],
matchIndex: matchIndex
});
// replaceFn has to return the node that replaced the endNode
// and then we step back so we can continue from the end of the
// match:
atIndex -= (endNode.length - endNodeIndex);
startNode = null;
endNode = null;
innerNodes = [];
matchLocation = matches.shift();
matchIndex++;
if (!matchLocation) {
break; // no more matches
}
} else if ((!hiddenTextElementsMap[curNode.nodeName] || blockElementsMap[curNode.nodeName]) && curNode.firstChild) {
// Move down
curNode = curNode.firstChild;
continue;
} else if (curNode.nextSibling) {
// Move forward:
curNode = curNode.nextSibling;
continue;
}
// Move forward or up:
while (true) {
if (curNode.nextSibling) {
curNode = curNode.nextSibling;
break;
} else if (curNode.parentNode !== node) {
curNode = curNode.parentNode;
} else {
break out;
}
}
}
}
/**
* Generates the actual replaceFn which splits up text nodes
* and inserts the replacement element.
*/
function genReplacer(nodeName) {
var makeReplacementNode;
if (typeof nodeName != 'function') {
var stencilNode = nodeName.nodeType ? nodeName : doc.createElement(nodeName);
makeReplacementNode = function(fill, matchIndex) {
var clone = stencilNode.cloneNode(false);
clone.setAttribute('data-mce-index', matchIndex);
if (fill) {
clone.appendChild(doc.createTextNode(fill));
}
return clone;
};
} else {
makeReplacementNode = nodeName;
}
return function(range) {
var before, after, parentNode, startNode = range.startNode,
endNode = range.endNode, matchIndex = range.matchIndex;
if (startNode === endNode) {
var node = startNode;
parentNode = node.parentNode;
if (range.startNodeIndex > 0) {
// Add `before` text node (before the match)
before = doc.createTextNode(node.data.substring(0, range.startNodeIndex));
parentNode.insertBefore(before, node);
}
// Create the replacement node:
var el = makeReplacementNode(range.match[0], matchIndex);
parentNode.insertBefore(el, node);
if (range.endNodeIndex < node.length) {
// Add `after` text node (after the match)
after = doc.createTextNode(node.data.substring(range.endNodeIndex));
parentNode.insertBefore(after, node);
}
node.parentNode.removeChild(node);
return el;
} else {
// Replace startNode -> [innerNodes...] -> endNode (in that order)
before = doc.createTextNode(startNode.data.substring(0, range.startNodeIndex));
after = doc.createTextNode(endNode.data.substring(range.endNodeIndex));
var elA = makeReplacementNode(startNode.data.substring(range.startNodeIndex), matchIndex);
var innerEls = [];
for (var i = 0, l = range.innerNodes.length; i < l; ++i) {
var innerNode = range.innerNodes[i];
var innerEl = makeReplacementNode(innerNode.data, matchIndex);
innerNode.parentNode.replaceChild(innerEl, innerNode);
innerEls.push(innerEl);
}
var elB = makeReplacementNode(endNode.data.substring(0, range.endNodeIndex), matchIndex);
parentNode = startNode.parentNode;
parentNode.insertBefore(before, startNode);
parentNode.insertBefore(elA, startNode);
parentNode.removeChild(startNode);
parentNode = endNode.parentNode;
parentNode.insertBefore(elB, endNode);
parentNode.insertBefore(after, endNode);
parentNode.removeChild(endNode);
return elB;
}
};
}
text = getText(node);
if (!text) {
return;
}
if (regex.global) {
while ((m = regex.exec(text))) {
matches.push(getMatchIndexes(m, captureGroup));
}
} else {
m = text.match(regex);
matches.push(getMatchIndexes(m, captureGroup));
}
if (matches.length) {
count = matches.length;
stepThroughMatches(node, matches, genReplacer(replacementNode));
}
return count;
}
function Plugin(editor) {
var self = this, currentIndex = -1;
function showDialog() {
var last = {};
function updateButtonStates() {
win.statusbar.find('#next').disabled(!findSpansByIndex(currentIndex + 1).length);
win.statusbar.find('#prev').disabled(!findSpansByIndex(currentIndex - 1).length);
}
function notFoundAlert() {
tinymce.ui.MessageBox.alert('Could not find the specified string.', function() {
win.find('#find')[0].focus();
});
}
var win = tinymce.ui.Factory.create({
type: 'window',
layout: "flex",
pack: "center",
align: "center",
onClose: function() {
editor.focus();
self.done();
},
onSubmit: function(e) {
var count, caseState, text, wholeWord;
e.preventDefault();
caseState = win.find('#case').checked();
wholeWord = win.find('#words').checked();
text = win.find('#find').value();
if (!text.length) {
self.done(false);
win.statusbar.items().slice(1).disabled(true);
return;
}
if (last.text == text && last.caseState == caseState && last.wholeWord == wholeWord) {
if (findSpansByIndex(currentIndex + 1).length === 0) {
notFoundAlert();
return;
}
self.next();
updateButtonStates();
return;
}
count = self.find(text, caseState, wholeWord);
if (!count) {
notFoundAlert();
}
win.statusbar.items().slice(1).disabled(count === 0);
updateButtonStates();
last = {
text: text,
caseState: caseState,
wholeWord: wholeWord
};
},
buttons: [
{text: "Find", onclick: function() {
win.submit();
}},
{text: "Replace", disabled: true, onclick: function() {
if (!self.replace(win.find('#replace').value())) {
win.statusbar.items().slice(1).disabled(true);
currentIndex = -1;
last = {};
}
}},
{text: "Replace all", disabled: true, onclick: function() {
self.replace(win.find('#replace').value(), true, true);
win.statusbar.items().slice(1).disabled(true);
last = {};
}},
{type: "spacer", flex: 1},
{text: "Prev", name: 'prev', disabled: true, onclick: function() {
self.prev();
updateButtonStates();
}},
{text: "Next", name: 'next', disabled: true, onclick: function() {
self.next();
updateButtonStates();
}}
],
title: "Find and replace",
items: {
type: "form",
padding: 20,
labelGap: 30,
spacing: 10,
items: [
{type: 'textbox', name: 'find', size: 40, label: 'Find', value: editor.selection.getNode().src},
{type: 'textbox', name: 'replace', size: 40, label: 'Replace with'},
{type: 'checkbox', name: 'case', text: 'Match case', label: ' '},
{type: 'checkbox', name: 'words', text: 'Whole words', label: ' '}
]
}
}).renderTo().reflow();
}
self.init = function(ed) {
ed.addMenuItem('searchreplace', {
text: 'Find and replace',
shortcut: 'Ctrl+F',
onclick: showDialog,
separator: 'before',
context: 'edit'
});
ed.addButton('searchreplace', {
tooltip: 'Find and replace',
shortcut: 'Ctrl+F',
onclick: showDialog
});
ed.addCommand("SearchReplace", showDialog);
ed.shortcuts.add('Ctrl+F', '', showDialog);
};
function getElmIndex(elm) {
var value = elm.getAttribute('data-mce-index');
if (typeof(value) == "number") {
return "" + value;
}
return value;
}
function markAllMatches(regex) {
var node, marker;
marker = editor.dom.create('span', {
"data-mce-bogus": 1
});
marker.className = 'mce-match-marker'; // IE 7 adds class="mce-match-marker" and class=mce-match-marker
node = editor.getBody();
self.done(false);
return findAndReplaceDOMText(regex, node, marker, false, editor.schema);
}
function unwrap(node) {
var parentNode = node.parentNode;
if (node.firstChild) {
parentNode.insertBefore(node.firstChild, node);
}
node.parentNode.removeChild(node);
}
function findSpansByIndex(index) {
var nodes, spans = [];
nodes = tinymce.toArray(editor.getBody().getElementsByTagName('span'));
if (nodes.length) {
for (var i = 0; i < nodes.length; i++) {
var nodeIndex = getElmIndex(nodes[i]);
if (nodeIndex === null || !nodeIndex.length) {
continue;
}
if (nodeIndex === index.toString()) {
spans.push(nodes[i]);
}
}
}
return spans;
}
function moveSelection(forward) {
var testIndex = currentIndex, dom = editor.dom;
forward = forward !== false;
if (forward) {
testIndex++;
} else {
testIndex--;
}
dom.removeClass(findSpansByIndex(currentIndex), 'mce-match-marker-selected');
var spans = findSpansByIndex(testIndex);
if (spans.length) {
dom.addClass(findSpansByIndex(testIndex), 'mce-match-marker-selected');
editor.selection.scrollIntoView(spans[0]);
return testIndex;
}
return -1;
}
function removeNode(node) {
node.parentNode.removeChild(node);
}
self.find = function(text, matchCase, wholeWord) {
text = text.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
text = wholeWord ? '\\b' + text + '\\b' : text;
var count = markAllMatches(new RegExp(text, matchCase ? 'g' : 'gi'));
if (count) {
currentIndex = -1;
currentIndex = moveSelection(true);
}
return count;
};
self.next = function() {
var index = moveSelection(true);
if (index !== -1) {
currentIndex = index;
}
};
self.prev = function() {
var index = moveSelection(false);
if (index !== -1) {
currentIndex = index;
}
};
self.replace = function(text, forward, all) {
var i, nodes, node, matchIndex, currentMatchIndex, nextIndex = currentIndex, hasMore;
forward = forward !== false;
node = editor.getBody();
nodes = tinymce.toArray(node.getElementsByTagName('span'));
for (i = 0; i < nodes.length; i++) {
var nodeIndex = getElmIndex(nodes[i]);
if (nodeIndex === null || !nodeIndex.length) {
continue;
}
matchIndex = currentMatchIndex = parseInt(nodeIndex, 10);
if (all || matchIndex === currentIndex) {
if (text.length) {
nodes[i].firstChild.nodeValue = text;
unwrap(nodes[i]);
} else {
removeNode(nodes[i]);
}
while (nodes[++i]) {
matchIndex = getElmIndex(nodes[i]);
if (nodeIndex === null || !nodeIndex.length) {
continue;
}
if (matchIndex === currentMatchIndex) {
removeNode(nodes[i]);
} else {
i--;
break;
}
}
if (forward) {
nextIndex--;
}
} else if (currentMatchIndex > currentIndex) {
nodes[i].setAttribute('data-mce-index', currentMatchIndex - 1);
}
}
editor.undoManager.add();
currentIndex = nextIndex;
if (forward) {
hasMore = findSpansByIndex(nextIndex + 1).length > 0;
self.next();
} else {
hasMore = findSpansByIndex(nextIndex - 1).length > 0;
self.prev();
}
return !all && hasMore;
};
self.done = function(keepEditorSelection) {
var i, nodes, startContainer, endContainer;
nodes = tinymce.toArray(editor.getBody().getElementsByTagName('span'));
for (i = 0; i < nodes.length; i++) {
var nodeIndex = getElmIndex(nodes[i]);
if (nodeIndex !== null && nodeIndex.length) {
if (nodeIndex === currentIndex.toString()) {
if (!startContainer) {
startContainer = nodes[i].firstChild;
}
endContainer = nodes[i].firstChild;
}
unwrap(nodes[i]);
}
}
if (startContainer && endContainer) {
var rng = editor.dom.createRng();
rng.setStart(startContainer, 0);
rng.setEnd(endContainer, endContainer.data.length);
if (keepEditorSelection !== false) {
editor.selection.setRng(rng);
}
return rng;
}
};
}
tinymce.PluginManager.add('searchreplace', Plugin);
})();

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,996 @@
/**
* Compiled inline version. (Library mode)
*/
/*jshint smarttabs:true, undef:true, latedef:true, curly:true, bitwise:true, camelcase:true */
/*globals $code */
(function(exports, undefined) {
"use strict";
var modules = {};
function require(ids, callback) {
var module, defs = [];
for (var i = 0; i < ids.length; ++i) {
module = modules[ids[i]] || resolve(ids[i]);
if (!module) {
throw 'module definition dependecy not found: ' + ids[i];
}
defs.push(module);
}
callback.apply(null, defs);
}
function define(id, dependencies, definition) {
if (typeof id !== 'string') {
throw 'invalid module definition, module id must be defined and be a string';
}
if (dependencies === undefined) {
throw 'invalid module definition, dependencies must be specified';
}
if (definition === undefined) {
throw 'invalid module definition, definition function must be specified';
}
require(dependencies, function() {
modules[id] = definition.apply(null, arguments);
});
}
function defined(id) {
return !!modules[id];
}
function resolve(id) {
var target = exports;
var fragments = id.split(/[.\/]/);
for (var fi = 0; fi < fragments.length; ++fi) {
if (!target[fragments[fi]]) {
return;
}
target = target[fragments[fi]];
}
return target;
}
function expose(ids) {
for (var i = 0; i < ids.length; i++) {
var target = exports;
var id = ids[i];
var fragments = id.split(/[.\/]/);
for (var fi = 0; fi < fragments.length - 1; ++fi) {
if (target[fragments[fi]] === undefined) {
target[fragments[fi]] = {};
}
target = target[fragments[fi]];
}
target[fragments[fragments.length - 1]] = modules[id];
}
}
// Included from: js/tinymce/plugins/spellchecker/classes/DomTextMatcher.js
/**
* DomTextMatcher.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*eslint no-labels:0, no-constant-condition: 0 */
/**
* This class logic for filtering text and matching words.
*
* @class tinymce.spellcheckerplugin.TextFilter
* @private
*/
define("tinymce/spellcheckerplugin/DomTextMatcher", [], function() {
// Based on work developed by: James Padolsey http://james.padolsey.com
// released under UNLICENSE that is compatible with LGPL
// TODO: Handle contentEditable edgecase:
// <p>text<span contentEditable="false">text<span contentEditable="true">text</span>text</span>text</p>
return function(node, editor) {
var m, matches = [], text, dom = editor.dom;
var blockElementsMap, hiddenTextElementsMap, shortEndedElementsMap;
blockElementsMap = editor.schema.getBlockElements(); // H1-H6, P, TD etc
hiddenTextElementsMap = editor.schema.getWhiteSpaceElements(); // TEXTAREA, PRE, STYLE, SCRIPT
shortEndedElementsMap = editor.schema.getShortEndedElements(); // BR, IMG, INPUT
function createMatch(m, data) {
if (!m[0]) {
throw 'findAndReplaceDOMText cannot handle zero-length matches';
}
return {
start: m.index,
end: m.index + m[0].length,
text: m[0],
data: data
};
}
function getText(node) {
var txt;
if (node.nodeType === 3) {
return node.data;
}
if (hiddenTextElementsMap[node.nodeName] && !blockElementsMap[node.nodeName]) {
return '';
}
txt = '';
if (blockElementsMap[node.nodeName] || shortEndedElementsMap[node.nodeName]) {
txt += '\n';
}
if ((node = node.firstChild)) {
do {
txt += getText(node);
} while ((node = node.nextSibling));
}
return txt;
}
function stepThroughMatches(node, matches, replaceFn) {
var startNode, endNode, startNodeIndex,
endNodeIndex, innerNodes = [], atIndex = 0, curNode = node,
matchLocation, matchIndex = 0;
matches = matches.slice(0);
matches.sort(function(a, b) {
return a.start - b.start;
});
matchLocation = matches.shift();
out: while (true) {
if (blockElementsMap[curNode.nodeName] || shortEndedElementsMap[curNode.nodeName]) {
atIndex++;
}
if (curNode.nodeType === 3) {
if (!endNode && curNode.length + atIndex >= matchLocation.end) {
// We've found the ending
endNode = curNode;
endNodeIndex = matchLocation.end - atIndex;
} else if (startNode) {
// Intersecting node
innerNodes.push(curNode);
}
if (!startNode && curNode.length + atIndex > matchLocation.start) {
// We've found the match start
startNode = curNode;
startNodeIndex = matchLocation.start - atIndex;
}
atIndex += curNode.length;
}
if (startNode && endNode) {
curNode = replaceFn({
startNode: startNode,
startNodeIndex: startNodeIndex,
endNode: endNode,
endNodeIndex: endNodeIndex,
innerNodes: innerNodes,
match: matchLocation.text,
matchIndex: matchIndex
});
// replaceFn has to return the node that replaced the endNode
// and then we step back so we can continue from the end of the
// match:
atIndex -= (endNode.length - endNodeIndex);
startNode = null;
endNode = null;
innerNodes = [];
matchLocation = matches.shift();
matchIndex++;
if (!matchLocation) {
break; // no more matches
}
} else if ((!hiddenTextElementsMap[curNode.nodeName] || blockElementsMap[curNode.nodeName]) && curNode.firstChild) {
// Move down
curNode = curNode.firstChild;
continue;
} else if (curNode.nextSibling) {
// Move forward:
curNode = curNode.nextSibling;
continue;
}
// Move forward or up:
while (true) {
if (curNode.nextSibling) {
curNode = curNode.nextSibling;
break;
} else if (curNode.parentNode !== node) {
curNode = curNode.parentNode;
} else {
break out;
}
}
}
}
/**
* Generates the actual replaceFn which splits up text nodes
* and inserts the replacement element.
*/
function genReplacer(callback) {
function makeReplacementNode(fill, matchIndex) {
var match = matches[matchIndex];
if (!match.stencil) {
match.stencil = callback(match);
}
var clone = match.stencil.cloneNode(false);
clone.setAttribute('data-mce-index', matchIndex);
if (fill) {
clone.appendChild(dom.doc.createTextNode(fill));
}
return clone;
}
return function(range) {
var before, after, parentNode, startNode = range.startNode,
endNode = range.endNode, matchIndex = range.matchIndex,
doc = dom.doc;
if (startNode === endNode) {
var node = startNode;
parentNode = node.parentNode;
if (range.startNodeIndex > 0) {
// Add "before" text node (before the match)
before = doc.createTextNode(node.data.substring(0, range.startNodeIndex));
parentNode.insertBefore(before, node);
}
// Create the replacement node:
var el = makeReplacementNode(range.match, matchIndex);
parentNode.insertBefore(el, node);
if (range.endNodeIndex < node.length) {
// Add "after" text node (after the match)
after = doc.createTextNode(node.data.substring(range.endNodeIndex));
parentNode.insertBefore(after, node);
}
node.parentNode.removeChild(node);
return el;
} else {
// Replace startNode -> [innerNodes...] -> endNode (in that order)
before = doc.createTextNode(startNode.data.substring(0, range.startNodeIndex));
after = doc.createTextNode(endNode.data.substring(range.endNodeIndex));
var elA = makeReplacementNode(startNode.data.substring(range.startNodeIndex), matchIndex);
var innerEls = [];
for (var i = 0, l = range.innerNodes.length; i < l; ++i) {
var innerNode = range.innerNodes[i];
var innerEl = makeReplacementNode(innerNode.data, matchIndex);
innerNode.parentNode.replaceChild(innerEl, innerNode);
innerEls.push(innerEl);
}
var elB = makeReplacementNode(endNode.data.substring(0, range.endNodeIndex), matchIndex);
parentNode = startNode.parentNode;
parentNode.insertBefore(before, startNode);
parentNode.insertBefore(elA, startNode);
parentNode.removeChild(startNode);
parentNode = endNode.parentNode;
parentNode.insertBefore(elB, endNode);
parentNode.insertBefore(after, endNode);
parentNode.removeChild(endNode);
return elB;
}
};
}
function unwrapElement(element) {
var parentNode = element.parentNode;
parentNode.insertBefore(element.firstChild, element);
element.parentNode.removeChild(element);
}
function getWrappersByIndex(index) {
var elements = node.getElementsByTagName('*'), wrappers = [];
index = typeof(index) == "number" ? "" + index : null;
for (var i = 0; i < elements.length; i++) {
var element = elements[i], dataIndex = element.getAttribute('data-mce-index');
if (dataIndex !== null && dataIndex.length) {
if (dataIndex === index || index === null) {
wrappers.push(element);
}
}
}
return wrappers;
}
/**
* Returns the index of a specific match object or -1 if it isn't found.
*
* @param {Match} match Text match object.
* @return {Number} Index of match or -1 if it isn't found.
*/
function indexOf(match) {
var i = matches.length;
while (i--) {
if (matches[i] === match) {
return i;
}
}
return -1;
}
/**
* Filters the matches. If the callback returns true it stays if not it gets removed.
*
* @param {Function} callback Callback to execute for each match.
* @return {DomTextMatcher} Current DomTextMatcher instance.
*/
function filter(callback) {
var filteredMatches = [];
each(function(match, i) {
if (callback(match, i)) {
filteredMatches.push(match);
}
});
matches = filteredMatches;
/*jshint validthis:true*/
return this;
}
/**
* Executes the specified callback for each match.
*
* @param {Function} callback Callback to execute for each match.
* @return {DomTextMatcher} Current DomTextMatcher instance.
*/
function each(callback) {
for (var i = 0, l = matches.length; i < l; i++) {
if (callback(matches[i], i) === false) {
break;
}
}
/*jshint validthis:true*/
return this;
}
/**
* Wraps the current matches with nodes created by the specified callback.
* Multiple clones of these matches might occur on matches that are on multiple nodex.
*
* @param {Function} callback Callback to execute in order to create elements for matches.
* @return {DomTextMatcher} Current DomTextMatcher instance.
*/
function wrap(callback) {
if (matches.length) {
stepThroughMatches(node, matches, genReplacer(callback));
}
/*jshint validthis:true*/
return this;
}
/**
* Finds the specified regexp and adds them to the matches collection.
*
* @param {RegExp} regex Global regexp to search the current node by.
* @param {Object} [data] Optional custom data element for the match.
* @return {DomTextMatcher} Current DomTextMatcher instance.
*/
function find(regex, data) {
if (text && regex.global) {
while ((m = regex.exec(text))) {
matches.push(createMatch(m, data));
}
}
return this;
}
/**
* Unwraps the specified match object or all matches if unspecified.
*
* @param {Object} [match] Optional match object.
* @return {DomTextMatcher} Current DomTextMatcher instance.
*/
function unwrap(match) {
var i, elements = getWrappersByIndex(match ? indexOf(match) : null);
i = elements.length;
while (i--) {
unwrapElement(elements[i]);
}
return this;
}
/**
* Returns a match object by the specified DOM element.
*
* @param {DOMElement} element Element to return match object for.
* @return {Object} Match object for the specified element.
*/
function matchFromElement(element) {
return matches[element.getAttribute('data-mce-index')];
}
/**
* Returns a DOM element from the specified match element. This will be the first element if it's split
* on multiple nodes.
*
* @param {Object} match Match element to get first element of.
* @return {DOMElement} DOM element for the specified match object.
*/
function elementFromMatch(match) {
return getWrappersByIndex(indexOf(match))[0];
}
/**
* Adds match the specified range for example a grammar line.
*
* @param {Number} start Start offset.
* @param {Number} length Length of the text.
* @param {Object} data Custom data object for match.
* @return {DomTextMatcher} Current DomTextMatcher instance.
*/
function add(start, length, data) {
matches.push({
start: start,
end: start + length,
text: text.substr(start, length),
data: data
});
return this;
}
/**
* Returns a DOM range for the specified match.
*
* @param {Object} match Match object to get range for.
* @return {DOMRange} DOM Range for the specified match.
*/
function rangeFromMatch(match) {
var wrappers = getWrappersByIndex(indexOf(match));
var rng = editor.dom.createRng();
rng.setStartBefore(wrappers[0]);
rng.setEndAfter(wrappers[wrappers.length - 1]);
return rng;
}
/**
* Replaces the specified match with the specified text.
*
* @param {Object} match Match object to replace.
* @param {String} text Text to replace the match with.
* @return {DOMRange} DOM range produced after the replace.
*/
function replace(match, text) {
var rng = rangeFromMatch(match);
rng.deleteContents();
if (text.length > 0) {
rng.insertNode(editor.dom.doc.createTextNode(text));
}
return rng;
}
/**
* Resets the DomTextMatcher instance. This will remove any wrapped nodes and remove any matches.
*
* @return {[type]} [description]
*/
function reset() {
matches.splice(0, matches.length);
unwrap();
return this;
}
text = getText(node);
return {
text: text,
matches: matches,
each: each,
filter: filter,
reset: reset,
matchFromElement: matchFromElement,
elementFromMatch: elementFromMatch,
find: find,
add: add,
wrap: wrap,
unwrap: unwrap,
replace: replace,
rangeFromMatch: rangeFromMatch,
indexOf: indexOf
};
};
});
// Included from: js/tinymce/plugins/spellchecker/classes/Plugin.js
/**
* Plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*jshint camelcase:false */
/**
* This class contains all core logic for the spellchecker plugin.
*
* @class tinymce.spellcheckerplugin.Plugin
* @private
*/
define("tinymce/spellcheckerplugin/Plugin", [
"tinymce/spellcheckerplugin/DomTextMatcher",
"tinymce/PluginManager",
"tinymce/util/Tools",
"tinymce/ui/Menu",
"tinymce/dom/DOMUtils",
"tinymce/util/XHR",
"tinymce/util/URI",
"tinymce/util/JSON"
], function(DomTextMatcher, PluginManager, Tools, Menu, DOMUtils, XHR, URI, JSON) {
PluginManager.add('spellchecker', function(editor, url) {
var languageMenuItems, self = this, lastSuggestions, started, suggestionsMenu, settings = editor.settings;
var hasDictionarySupport;
function getTextMatcher() {
if (!self.textMatcher) {
self.textMatcher = new DomTextMatcher(editor.getBody(), editor);
}
return self.textMatcher;
}
function buildMenuItems(listName, languageValues) {
var items = [];
Tools.each(languageValues, function(languageValue) {
items.push({
selectable: true,
text: languageValue.name,
data: languageValue.value
});
});
return items;
}
var languagesString = settings.spellchecker_languages ||
'English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr_FR,' +
'German=de,Italian=it,Polish=pl,Portuguese=pt_BR,' +
'Spanish=es,Swedish=sv';
languageMenuItems = buildMenuItems('Language',
Tools.map(languagesString.split(','), function(langPair) {
langPair = langPair.split('=');
return {
name: langPair[0],
value: langPair[1]
};
})
);
function isEmpty(obj) {
/*jshint unused:false*/
/*eslint no-unused-vars:0 */
for (var name in obj) {
return false;
}
return true;
}
function showSuggestions(word, spans) {
var items = [], suggestions = lastSuggestions[word];
Tools.each(suggestions, function(suggestion) {
items.push({
text: suggestion,
onclick: function() {
editor.insertContent(editor.dom.encode(suggestion));
editor.dom.remove(spans);
checkIfFinished();
}
});
});
items.push({text: '-'});
if (hasDictionarySupport) {
items.push({text: 'Add to Dictionary', onclick: function() {
addToDictionary(word, spans);
}});
}
items.push.apply(items, [
{text: 'Ignore', onclick: function() {
ignoreWord(word, spans);
}},
{text: 'Ignore all', onclick: function() {
ignoreWord(word, spans, true);
}}
]);
// Render menu
suggestionsMenu = new Menu({
items: items,
context: 'contextmenu',
onautohide: function(e) {
if (e.target.className.indexOf('spellchecker') != -1) {
e.preventDefault();
}
},
onhide: function() {
suggestionsMenu.remove();
suggestionsMenu = null;
}
});
suggestionsMenu.renderTo(document.body);
// Position menu
var pos = DOMUtils.DOM.getPos(editor.getContentAreaContainer());
var targetPos = editor.dom.getPos(spans[0]);
var root = editor.dom.getRoot();
// Adjust targetPos for scrolling in the editor
if (root.nodeName == 'BODY') {
targetPos.x -= root.ownerDocument.documentElement.scrollLeft || root.scrollLeft;
targetPos.y -= root.ownerDocument.documentElement.scrollTop || root.scrollTop;
} else {
targetPos.x -= root.scrollLeft;
targetPos.y -= root.scrollTop;
}
pos.x += targetPos.x;
pos.y += targetPos.y;
suggestionsMenu.moveTo(pos.x, pos.y + spans[0].offsetHeight);
}
function getWordCharPattern() {
// Regexp for finding word specific characters this will split words by
// spaces, quotes, copy right characters etc. It's escaped with unicode characters
// to make it easier to output scripts on servers using different encodings
// so if you add any characters outside the 128 byte range make sure to escape it
return editor.getParam('spellchecker_wordchar_pattern') || new RegExp("[^" +
"\\s!\"#$%&()*+,-./:;<=>?@[\\]^_{|}`" +
"\u00a7\u00a9\u00ab\u00ae\u00b1\u00b6\u00b7\u00b8\u00bb" +
"\u00bc\u00bd\u00be\u00bf\u00d7\u00f7\u00a4\u201d\u201c\u201e\u00a0\u2002\u2003\u2009" +
"]+", "g");
}
function defaultSpellcheckCallback(method, text, doneCallback, errorCallback) {
var data = {method: method}, postData = '';
if (method == "spellcheck") {
data.text = text;
data.lang = settings.spellchecker_language;
}
if (method == "addToDictionary") {
data.word = text;
}
Tools.each(data, function(value, key) {
if (postData) {
postData += '&';
}
postData += key + '=' + encodeURIComponent(value);
});
XHR.send({
url: new URI(url).toAbsolute(settings.spellchecker_rpc_url),
type: "post",
content_type: 'application/x-www-form-urlencoded',
data: postData,
success: function(result) {
result = JSON.parse(result);
if (!result) {
errorCallback("Sever response wasn't proper JSON.");
} else if (result.error) {
errorCallback(result.error);
} else {
doneCallback(result);
}
},
error: function(type, xhr) {
errorCallback("Spellchecker request error: " + xhr.status);
}
});
}
function sendRpcCall(name, data, successCallback, errorCallback) {
var spellCheckCallback = settings.spellchecker_callback || defaultSpellcheckCallback;
spellCheckCallback.call(self, name, data, successCallback, errorCallback);
}
function spellcheck() {
if (started) {
finish();
return;
} else {
finish();
}
function errorCallback(message) {
editor.windowManager.alert(message);
editor.setProgressState(false);
finish();
}
editor.setProgressState(true);
sendRpcCall("spellcheck", getTextMatcher().text, markErrors, errorCallback);
editor.focus();
}
function checkIfFinished() {
if (!editor.dom.select('span.mce-spellchecker-word').length) {
finish();
}
}
function addToDictionary(word, spans) {
editor.setProgressState(true);
sendRpcCall("addToDictionary", word, function() {
editor.setProgressState(false);
editor.dom.remove(spans, true);
checkIfFinished();
}, function(message) {
editor.windowManager.alert(message);
editor.setProgressState(false);
});
}
function ignoreWord(word, spans, all) {
editor.selection.collapse();
if (all) {
Tools.each(editor.dom.select('span.mce-spellchecker-word'), function(span) {
if (span.getAttribute('data-mce-word') == word) {
editor.dom.remove(span, true);
}
});
} else {
editor.dom.remove(spans, true);
}
checkIfFinished();
}
function finish() {
getTextMatcher().reset();
self.textMatcher = null;
if (started) {
started = false;
editor.fire('SpellcheckEnd');
}
}
function getElmIndex(elm) {
var value = elm.getAttribute('data-mce-index');
if (typeof(value) == "number") {
return "" + value;
}
return value;
}
function findSpansByIndex(index) {
var nodes, spans = [];
nodes = Tools.toArray(editor.getBody().getElementsByTagName('span'));
if (nodes.length) {
for (var i = 0; i < nodes.length; i++) {
var nodeIndex = getElmIndex(nodes[i]);
if (nodeIndex === null || !nodeIndex.length) {
continue;
}
if (nodeIndex === index.toString()) {
spans.push(nodes[i]);
}
}
}
return spans;
}
editor.on('click', function(e) {
var target = e.target;
if (target.className == "mce-spellchecker-word") {
e.preventDefault();
var spans = findSpansByIndex(getElmIndex(target));
if (spans.length > 0) {
var rng = editor.dom.createRng();
rng.setStartBefore(spans[0]);
rng.setEndAfter(spans[spans.length - 1]);
editor.selection.setRng(rng);
showSuggestions(target.getAttribute('data-mce-word'), spans);
}
}
});
editor.addMenuItem('spellchecker', {
text: 'Spellcheck',
context: 'tools',
onclick: spellcheck,
selectable: true,
onPostRender: function() {
var self = this;
self.active(started);
editor.on('SpellcheckStart SpellcheckEnd', function() {
self.active(started);
});
}
});
function updateSelection(e) {
var selectedLanguage = settings.spellchecker_language;
e.control.items().each(function(ctrl) {
ctrl.active(ctrl.settings.data === selectedLanguage);
});
}
/**
* Find the specified words and marks them. It will also show suggestions for those words.
*
* @example
* editor.plugins.spellchecker.markErrors({
* dictionary: true,
* words: {
* "word1": ["suggestion 1", "Suggestion 2"]
* }
* });
* @param {Object} data Data object containing the words with suggestions.
*/
function markErrors(data) {
var suggestions;
if (data.words) {
hasDictionarySupport = !!data.dictionary;
suggestions = data.words;
} else {
// Fallback to old format
suggestions = data;
}
editor.setProgressState(false);
if (isEmpty(suggestions)) {
editor.windowManager.alert('No misspellings found');
started = false;
return;
}
lastSuggestions = suggestions;
getTextMatcher().find(getWordCharPattern()).filter(function(match) {
return !!suggestions[match.text];
}).wrap(function(match) {
return editor.dom.create('span', {
"class": 'mce-spellchecker-word',
"data-mce-bogus": 1,
"data-mce-word": match.text
});
});
started = true;
editor.fire('SpellcheckStart');
}
var buttonArgs = {
tooltip: 'Spellcheck',
onclick: spellcheck,
onPostRender: function() {
var self = this;
editor.on('SpellcheckStart SpellcheckEnd', function() {
self.active(started);
});
}
};
if (languageMenuItems.length > 1) {
buttonArgs.type = 'splitbutton';
buttonArgs.menu = languageMenuItems;
buttonArgs.onshow = updateSelection;
buttonArgs.onselect = function(e) {
settings.spellchecker_language = e.control.settings.data;
};
}
editor.addButton('spellchecker', buttonArgs);
editor.addCommand('mceSpellCheck', spellcheck);
editor.on('remove', function() {
if (suggestionsMenu) {
suggestionsMenu.remove();
suggestionsMenu = null;
}
});
editor.on('change', checkIfFinished);
this.getTextMatcher = getTextMatcher;
this.getWordCharPattern = getWordCharPattern;
this.markErrors = markErrors;
this.getLanguage = function() {
return settings.spellchecker_language;
};
// Set default spellchecker language if it's not specified
settings.spellchecker_language = settings.spellchecker_language || settings.language || 'en';
});
});
expose(["tinymce/spellcheckerplugin/DomTextMatcher"]);
})(this);

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,120 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('tabfocus', function(editor) {
var DOM = tinymce.DOM, each = tinymce.each, explode = tinymce.explode;
function tabCancel(e) {
if (e.keyCode === 9 && !e.ctrlKey && !e.altKey && !e.metaKey) {
e.preventDefault();
}
}
function tabHandler(e) {
var x, el, v, i;
if (e.keyCode !== 9 || e.ctrlKey || e.altKey || e.metaKey || e.isDefaultPrevented()) {
return;
}
function find(direction) {
el = DOM.select(':input:enabled,*[tabindex]:not(iframe)');
function canSelectRecursive(e) {
return e.nodeName === "BODY" || (e.type != 'hidden' &&
e.style.display != "none" &&
e.style.visibility != "hidden" && canSelectRecursive(e.parentNode));
}
function canSelect(el) {
return /INPUT|TEXTAREA|BUTTON/.test(el.tagName) && tinymce.get(e.id) && el.tabIndex != -1 && canSelectRecursive(el);
}
each(el, function(e, i) {
if (e.id == editor.id) {
x = i;
return false;
}
});
if (direction > 0) {
for (i = x + 1; i < el.length; i++) {
if (canSelect(el[i])) {
return el[i];
}
}
} else {
for (i = x - 1; i >= 0; i--) {
if (canSelect(el[i])) {
return el[i];
}
}
}
return null;
}
v = explode(editor.getParam('tab_focus', editor.getParam('tabfocus_elements', ':prev,:next')));
if (v.length == 1) {
v[1] = v[0];
v[0] = ':prev';
}
// Find element to focus
if (e.shiftKey) {
if (v[0] == ':prev') {
el = find(-1);
} else {
el = DOM.get(v[0]);
}
} else {
if (v[1] == ':next') {
el = find(1);
} else {
el = DOM.get(v[1]);
}
}
if (el) {
var focusEditor = tinymce.get(el.id || el.name);
if (el.id && focusEditor) {
focusEditor.focus();
} else {
window.setTimeout(function() {
if (!tinymce.Env.webkit) {
window.focus();
}
el.focus();
}, 10);
}
e.preventDefault();
}
}
editor.on('init', function() {
if (editor.inline) {
// Remove default tabIndex in inline mode
tinymce.DOM.setAttrib(editor.getBody(), 'tabIndex', null);
}
editor.on('keyup', tabCancel);
if (tinymce.Env.gecko) {
editor.on('keypress keydown', tabHandler);
} else {
editor.on('keydown', tabHandler);
}
});
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("tabfocus",function(a){function b(a){9!==a.keyCode||a.ctrlKey||a.altKey||a.metaKey||a.preventDefault()}function c(b){function c(c){function f(a){return"BODY"===a.nodeName||"hidden"!=a.type&&"none"!=a.style.display&&"hidden"!=a.style.visibility&&f(a.parentNode)}function i(a){return/INPUT|TEXTAREA|BUTTON/.test(a.tagName)&&tinymce.get(b.id)&&-1!=a.tabIndex&&f(a)}if(h=d.select(":input:enabled,*[tabindex]:not(iframe)"),e(h,function(b,c){return b.id==a.id?(g=c,!1):void 0}),c>0){for(j=g+1;j<h.length;j++)if(i(h[j]))return h[j]}else for(j=g-1;j>=0;j--)if(i(h[j]))return h[j];return null}var g,h,i,j;if(!(9!==b.keyCode||b.ctrlKey||b.altKey||b.metaKey||b.isDefaultPrevented())&&(i=f(a.getParam("tab_focus",a.getParam("tabfocus_elements",":prev,:next"))),1==i.length&&(i[1]=i[0],i[0]=":prev"),h=b.shiftKey?":prev"==i[0]?c(-1):d.get(i[0]):":next"==i[1]?c(1):d.get(i[1]))){var k=tinymce.get(h.id||h.name);h.id&&k?k.focus():window.setTimeout(function(){tinymce.Env.webkit||window.focus(),h.focus()},10),b.preventDefault()}}var d=tinymce.DOM,e=tinymce.each,f=tinymce.explode;a.on("init",function(){a.inline&&tinymce.DOM.setAttrib(a.getBody(),"tabIndex",null),a.on("keyup",b),tinymce.Env.gecko?a.on("keypress keydown",c):a.on("keydown",c)})});

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,262 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('template', function(editor) {
var each = tinymce.each;
function createTemplateList(callback) {
return function() {
var templateList = editor.settings.templates;
if (typeof(templateList) == "string") {
tinymce.util.XHR.send({
url: templateList,
success: function(text) {
callback(tinymce.util.JSON.parse(text));
}
});
} else {
callback(templateList);
}
};
}
function showDialog(templateList) {
var win, values = [], templateHtml;
if (!templateList || templateList.length === 0) {
editor.windowManager.alert('No templates defined');
return;
}
tinymce.each(templateList, function(template) {
values.push({
selected: !values.length,
text: template.title,
value: {
url: template.url,
content: template.content,
description: template.description
}
});
});
function onSelectTemplate(e) {
var value = e.control.value();
function insertIframeHtml(html) {
if (html.indexOf('<html>') == -1) {
var contentCssLinks = '';
tinymce.each(editor.contentCSS, function(url) {
contentCssLinks += '<link type="text/css" rel="stylesheet" href="' + editor.documentBaseURI.toAbsolute(url) + '">';
});
html = (
'<!DOCTYPE html>' +
'<html>' +
'<head>' +
contentCssLinks +
'</head>' +
'<body>' +
html +
'</body>' +
'</html>'
);
}
html = replaceTemplateValues(html, 'template_preview_replace_values');
var doc = win.find('iframe')[0].getEl().contentWindow.document;
doc.open();
doc.write(html);
doc.close();
}
if (value.url) {
tinymce.util.XHR.send({
url: value.url,
success: function(html) {
templateHtml = html;
insertIframeHtml(templateHtml);
}
});
} else {
templateHtml = value.content;
insertIframeHtml(templateHtml);
}
win.find('#description')[0].text(e.control.value().description);
}
win = editor.windowManager.open({
title: 'Insert template',
layout: 'flex',
direction: 'column',
align: 'stretch',
padding: 15,
spacing: 10,
items: [
{type: 'form', flex: 0, padding: 0, items: [
{type: 'container', label: 'Templates', items: {
type: 'listbox', label: 'Templates', name: 'template', values: values, onselect: onSelectTemplate
}}
]},
{type: 'label', name: 'description', label: 'Description', text: '\u00a0'},
{type: 'iframe', flex: 1, border: 1}
],
onsubmit: function() {
insertTemplate(false, templateHtml);
},
width: editor.getParam('template_popup_width', 600),
height: editor.getParam('template_popup_height', 500)
});
win.find('listbox')[0].fire('select');
}
function getDateTime(fmt, date) {
var daysShort = "Sun Mon Tue Wed Thu Fri Sat Sun".split(' ');
var daysLong = "Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split(' ');
var monthsShort = "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(' ');
var monthsLong = "January February March April May June July August September October November December".split(' ');
function addZeros(value, len) {
value = "" + value;
if (value.length < len) {
for (var i = 0; i < (len - value.length); i++) {
value = "0" + value;
}
}
return value;
}
date = date || new Date();
fmt = fmt.replace("%D", "%m/%d/%Y");
fmt = fmt.replace("%r", "%I:%M:%S %p");
fmt = fmt.replace("%Y", "" + date.getFullYear());
fmt = fmt.replace("%y", "" + date.getYear());
fmt = fmt.replace("%m", addZeros(date.getMonth() + 1, 2));
fmt = fmt.replace("%d", addZeros(date.getDate(), 2));
fmt = fmt.replace("%H", "" + addZeros(date.getHours(), 2));
fmt = fmt.replace("%M", "" + addZeros(date.getMinutes(), 2));
fmt = fmt.replace("%S", "" + addZeros(date.getSeconds(), 2));
fmt = fmt.replace("%I", "" + ((date.getHours() + 11) % 12 + 1));
fmt = fmt.replace("%p", "" + (date.getHours() < 12 ? "AM" : "PM"));
fmt = fmt.replace("%B", "" + editor.translate(monthsLong[date.getMonth()]));
fmt = fmt.replace("%b", "" + editor.translate(monthsShort[date.getMonth()]));
fmt = fmt.replace("%A", "" + editor.translate(daysLong[date.getDay()]));
fmt = fmt.replace("%a", "" + editor.translate(daysShort[date.getDay()]));
fmt = fmt.replace("%%", "%");
return fmt;
}
function replaceVals(e) {
var dom = editor.dom, vl = editor.getParam('template_replace_values');
each(dom.select('*', e), function(e) {
each(vl, function(v, k) {
if (dom.hasClass(e, k)) {
if (typeof(vl[k]) == 'function') {
vl[k](e);
}
}
});
});
}
function replaceTemplateValues(html, templateValuesOptionName) {
each(editor.getParam(templateValuesOptionName), function(v, k) {
if (typeof(v) != 'function') {
html = html.replace(new RegExp('\\{\\$' + k + '\\}', 'g'), v);
}
});
return html;
}
function insertTemplate(ui, html) {
var el, n, dom = editor.dom, sel = editor.selection.getContent();
html = replaceTemplateValues(html, 'template_replace_values');
el = dom.create('div', null, html);
// Find template element within div
n = dom.select('.mceTmpl', el);
if (n && n.length > 0) {
el = dom.create('div', null);
el.appendChild(n[0].cloneNode(true));
}
function hasClass(n, c) {
return new RegExp('\\b' + c + '\\b', 'g').test(n.className);
}
each(dom.select('*', el), function(n) {
// Replace cdate
if (hasClass(n, editor.getParam('template_cdate_classes', 'cdate').replace(/\s+/g, '|'))) {
n.innerHTML = getDateTime(editor.getParam("template_cdate_format", editor.getLang("template.cdate_format")));
}
// Replace mdate
if (hasClass(n, editor.getParam('template_mdate_classes', 'mdate').replace(/\s+/g, '|'))) {
n.innerHTML = getDateTime(editor.getParam("template_mdate_format", editor.getLang("template.mdate_format")));
}
// Replace selection
if (hasClass(n, editor.getParam('template_selected_content_classes', 'selcontent').replace(/\s+/g, '|'))) {
n.innerHTML = sel;
}
});
replaceVals(el);
editor.execCommand('mceInsertContent', false, el.innerHTML);
editor.addVisual();
}
editor.addCommand('mceInsertTemplate', insertTemplate);
editor.addButton('template', {
title: 'Insert template',
onclick: createTemplateList(showDialog)
});
editor.addMenuItem('template', {
text: 'Insert template',
onclick: createTemplateList(showDialog),
context: 'insert'
});
editor.on('PreProcess', function(o) {
var dom = editor.dom;
each(dom.select('div', o.node), function(e) {
if (dom.hasClass(e, 'mceTmpl')) {
each(dom.select('*', e), function(e) {
if (dom.hasClass(e, editor.getParam('template_mdate_classes', 'mdate').replace(/\s+/g, '|'))) {
e.innerHTML = getDateTime(editor.getParam("template_mdate_format", editor.getLang("template.mdate_format")));
}
});
replaceVals(e);
}
});
});
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("template",function(a){function b(b){return function(){var c=a.settings.templates;"string"==typeof c?tinymce.util.XHR.send({url:c,success:function(a){b(tinymce.util.JSON.parse(a))}}):b(c)}}function c(b){function c(b){function c(b){if(-1==b.indexOf("<html>")){var c="";tinymce.each(a.contentCSS,function(b){c+='<link type="text/css" rel="stylesheet" href="'+a.documentBaseURI.toAbsolute(b)+'">'}),b="<!DOCTYPE html><html><head>"+c+"</head><body>"+b+"</body></html>"}b=f(b,"template_preview_replace_values");var e=d.find("iframe")[0].getEl().contentWindow.document;e.open(),e.write(b),e.close()}var g=b.control.value();g.url?tinymce.util.XHR.send({url:g.url,success:function(a){e=a,c(e)}}):(e=g.content,c(e)),d.find("#description")[0].text(b.control.value().description)}var d,e,h=[];return b&&0!==b.length?(tinymce.each(b,function(a){h.push({selected:!h.length,text:a.title,value:{url:a.url,content:a.content,description:a.description}})}),d=a.windowManager.open({title:"Insert template",layout:"flex",direction:"column",align:"stretch",padding:15,spacing:10,items:[{type:"form",flex:0,padding:0,items:[{type:"container",label:"Templates",items:{type:"listbox",label:"Templates",name:"template",values:h,onselect:c}}]},{type:"label",name:"description",label:"Description",text:"\xa0"},{type:"iframe",flex:1,border:1}],onsubmit:function(){g(!1,e)},width:a.getParam("template_popup_width",600),height:a.getParam("template_popup_height",500)}),void d.find("listbox")[0].fire("select")):void a.windowManager.alert("No templates defined")}function d(b,c){function d(a,b){if(a=""+a,a.length<b)for(var c=0;c<b-a.length;c++)a="0"+a;return a}var e="Sun Mon Tue Wed Thu Fri Sat Sun".split(" "),f="Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split(" "),g="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),h="January February March April May June July August September October November December".split(" ");return c=c||new Date,b=b.replace("%D","%m/%d/%Y"),b=b.replace("%r","%I:%M:%S %p"),b=b.replace("%Y",""+c.getFullYear()),b=b.replace("%y",""+c.getYear()),b=b.replace("%m",d(c.getMonth()+1,2)),b=b.replace("%d",d(c.getDate(),2)),b=b.replace("%H",""+d(c.getHours(),2)),b=b.replace("%M",""+d(c.getMinutes(),2)),b=b.replace("%S",""+d(c.getSeconds(),2)),b=b.replace("%I",""+((c.getHours()+11)%12+1)),b=b.replace("%p",""+(c.getHours()<12?"AM":"PM")),b=b.replace("%B",""+a.translate(h[c.getMonth()])),b=b.replace("%b",""+a.translate(g[c.getMonth()])),b=b.replace("%A",""+a.translate(f[c.getDay()])),b=b.replace("%a",""+a.translate(e[c.getDay()])),b=b.replace("%%","%")}function e(b){var c=a.dom,d=a.getParam("template_replace_values");h(c.select("*",b),function(a){h(d,function(b,e){c.hasClass(a,e)&&"function"==typeof d[e]&&d[e](a)})})}function f(b,c){return h(a.getParam(c),function(a,c){"function"!=typeof a&&(b=b.replace(new RegExp("\\{\\$"+c+"\\}","g"),a))}),b}function g(b,c){function g(a,b){return new RegExp("\\b"+b+"\\b","g").test(a.className)}var i,j,k=a.dom,l=a.selection.getContent();c=f(c,"template_replace_values"),i=k.create("div",null,c),j=k.select(".mceTmpl",i),j&&j.length>0&&(i=k.create("div",null),i.appendChild(j[0].cloneNode(!0))),h(k.select("*",i),function(b){g(b,a.getParam("template_cdate_classes","cdate").replace(/\s+/g,"|"))&&(b.innerHTML=d(a.getParam("template_cdate_format",a.getLang("template.cdate_format")))),g(b,a.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))&&(b.innerHTML=d(a.getParam("template_mdate_format",a.getLang("template.mdate_format")))),g(b,a.getParam("template_selected_content_classes","selcontent").replace(/\s+/g,"|"))&&(b.innerHTML=l)}),e(i),a.execCommand("mceInsertContent",!1,i.innerHTML),a.addVisual()}var h=tinymce.each;a.addCommand("mceInsertTemplate",g),a.addButton("template",{title:"Insert template",onclick:b(c)}),a.addMenuItem("template",{text:"Insert template",onclick:b(c),context:"insert"}),a.on("PreProcess",function(b){var c=a.dom;h(c.select("div",b.node),function(b){c.hasClass(b,"mceTmpl")&&(h(c.select("*",b),function(b){c.hasClass(b,a.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))&&(b.innerHTML=d(a.getParam("template_mdate_format",a.getLang("template.mdate_format"))))}),e(b))})})});

View File

@ -0,0 +1,272 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
/*eslint consistent-this:0 */
tinymce.PluginManager.add('textcolor', function(editor) {
var cols, rows;
rows = editor.settings.textcolor_rows || 5;
cols = editor.settings.textcolor_cols || 8;
function getCurrentColor(format) {
var color;
editor.dom.getParents(editor.selection.getStart(), function(elm) {
var value;
if ((value = elm.style[format == 'forecolor' ? 'color' : 'background-color'])) {
color = value;
}
});
return color;
}
function mapColors() {
var i, colors = [], colorMap;
colorMap = editor.settings.textcolor_map || [
"000000", "Black",
"993300", "Burnt orange",
"333300", "Dark olive",
"003300", "Dark green",
"003366", "Dark azure",
"000080", "Navy Blue",
"333399", "Indigo",
"333333", "Very dark gray",
"800000", "Maroon",
"FF6600", "Orange",
"808000", "Olive",
"008000", "Green",
"008080", "Teal",
"0000FF", "Blue",
"666699", "Grayish blue",
"808080", "Gray",
"FF0000", "Red",
"FF9900", "Amber",
"99CC00", "Yellow green",
"339966", "Sea green",
"33CCCC", "Turquoise",
"3366FF", "Royal blue",
"800080", "Purple",
"999999", "Medium gray",
"FF00FF", "Magenta",
"FFCC00", "Gold",
"FFFF00", "Yellow",
"00FF00", "Lime",
"00FFFF", "Aqua",
"00CCFF", "Sky blue",
"993366", "Red violet",
"FFFFFF", "White",
"FF99CC", "Pink",
"FFCC99", "Peach",
"FFFF99", "Light yellow",
"CCFFCC", "Pale green",
"CCFFFF", "Pale cyan",
"99CCFF", "Light sky blue",
"CC99FF", "Plum"
];
for (i = 0; i < colorMap.length; i += 2) {
colors.push({
text: colorMap[i + 1],
color: '#' + colorMap[i]
});
}
return colors;
}
function renderColorPicker() {
var ctrl = this, colors, color, html, last, x, y, i, id = ctrl._id, count = 0;
function getColorCellHtml(color, title) {
var isNoColor = color == 'transparent';
return (
'<td class="mce-grid-cell' + (isNoColor ? ' mce-colorbtn-trans' : '') + '">' +
'<div id="' + id + '-' + (count++) + '"' +
' data-mce-color="' + (color ? color : '') + '"' +
' role="option"' +
' tabIndex="-1"' +
' style="' + (color ? 'background-color: ' + color : '') + '"' +
' title="' + tinymce.translate(title) + '">' +
(isNoColor ? '&#215;' : '') +
'</div>' +
'</td>'
);
}
colors = mapColors();
colors.push({
text: tinymce.translate("No color"),
color: "transparent"
});
html = '<table class="mce-grid mce-grid-border mce-colorbutton-grid" role="list" cellspacing="0"><tbody>';
last = colors.length - 1;
for (y = 0; y < rows; y++) {
html += '<tr>';
for (x = 0; x < cols; x++) {
i = y * cols + x;
if (i > last) {
html += '<td></td>';
} else {
color = colors[i];
html += getColorCellHtml(color.color, color.text);
}
}
html += '</tr>';
}
if (editor.settings.color_picker_callback) {
html += (
'<tr>' +
'<td colspan="' + cols + '" class="mce-custom-color-btn">' +
'<div id="' + id + '-c" class="mce-widget mce-btn mce-btn-small mce-btn-flat" ' +
'role="button" tabindex="-1" aria-labelledby="' + id + '-c" style="width: 100%">' +
'<button type="button" role="presentation" tabindex="-1">' + tinymce.translate('Custom...') + '</button>' +
'</div>' +
'</td>' +
'</tr>'
);
html += '<tr>';
for (x = 0; x < cols; x++) {
html += getColorCellHtml('', 'Custom color');
}
html += '</tr>';
}
html += '</tbody></table>';
return html;
}
function applyFormat(format, value) {
editor.focus();
editor.formatter.apply(format, {value: value});
editor.nodeChanged();
}
function removeFormat(format) {
editor.focus();
editor.formatter.remove(format, {value: null}, null, true);
editor.nodeChanged();
}
function onPanelClick(e) {
var buttonCtrl = this.parent(), value;
function selectColor(value) {
buttonCtrl.hidePanel();
buttonCtrl.color(value);
applyFormat(buttonCtrl.settings.format, value);
}
function setDivColor(div, value) {
div.style.background = value;
div.setAttribute('data-mce-color', value);
}
if (tinymce.DOM.getParent(e.target, '.mce-custom-color-btn')) {
buttonCtrl.hidePanel();
editor.settings.color_picker_callback.call(editor, function(value) {
var tableElm = buttonCtrl.panel.getEl().getElementsByTagName('table')[0];
var customColorCells, div, i;
customColorCells = tinymce.map(tableElm.rows[tableElm.rows.length - 1].childNodes, function(elm) {
return elm.firstChild;
});
for (i = 0; i < customColorCells.length; i++) {
div = customColorCells[i];
if (!div.getAttribute('data-mce-color')) {
break;
}
}
// Shift colors to the right
// TODO: Might need to be the left on RTL
if (i == cols) {
for (i = 0; i < cols - 1; i++) {
setDivColor(customColorCells[i], customColorCells[i + 1].getAttribute('data-mce-color'));
}
}
setDivColor(div, value);
selectColor(value);
}, getCurrentColor(buttonCtrl.settings.format));
}
value = e.target.getAttribute('data-mce-color');
if (value) {
if (this.lastId) {
document.getElementById(this.lastId).setAttribute('aria-selected', false);
}
e.target.setAttribute('aria-selected', true);
this.lastId = e.target.id;
if (value == 'transparent') {
removeFormat(buttonCtrl.settings.format);
buttonCtrl.hidePanel();
return;
}
selectColor(value);
} else if (value !== null) {
buttonCtrl.hidePanel();
}
}
function onButtonClick() {
var self = this;
if (self._color) {
applyFormat(self.settings.format, self._color);
}
}
editor.addButton('forecolor', {
type: 'colorbutton',
tooltip: 'Text color',
format: 'forecolor',
panel: {
role: 'application',
ariaRemember: true,
html: renderColorPicker,
onclick: onPanelClick
},
onclick: onButtonClick
});
editor.addButton('backcolor', {
type: 'colorbutton',
tooltip: 'Background color',
format: 'hilitecolor',
panel: {
role: 'application',
ariaRemember: true,
html: renderColorPicker,
onclick: onPanelClick
},
onclick: onButtonClick
});
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("textcolor",function(a){function b(b){var c;return a.dom.getParents(a.selection.getStart(),function(a){var d;(d=a.style["forecolor"==b?"color":"background-color"])&&(c=d)}),c}function c(){var b,c,d=[];for(c=a.settings.textcolor_map||["000000","Black","993300","Burnt orange","333300","Dark olive","003300","Dark green","003366","Dark azure","000080","Navy Blue","333399","Indigo","333333","Very dark gray","800000","Maroon","FF6600","Orange","808000","Olive","008000","Green","008080","Teal","0000FF","Blue","666699","Grayish blue","808080","Gray","FF0000","Red","FF9900","Amber","99CC00","Yellow green","339966","Sea green","33CCCC","Turquoise","3366FF","Royal blue","800080","Purple","999999","Medium gray","FF00FF","Magenta","FFCC00","Gold","FFFF00","Yellow","00FF00","Lime","00FFFF","Aqua","00CCFF","Sky blue","993366","Red violet","FFFFFF","White","FF99CC","Pink","FFCC99","Peach","FFFF99","Light yellow","CCFFCC","Pale green","CCFFFF","Pale cyan","99CCFF","Light sky blue","CC99FF","Plum"],b=0;b<c.length;b+=2)d.push({text:c[b+1],color:"#"+c[b]});return d}function d(){function b(a,b){var c="transparent"==a;return'<td class="mce-grid-cell'+(c?" mce-colorbtn-trans":"")+'"><div id="'+n+"-"+o++ +'" data-mce-color="'+(a?a:"")+'" role="option" tabIndex="-1" style="'+(a?"background-color: "+a:"")+'" title="'+tinymce.translate(b)+'">'+(c?"&#215;":"")+"</div></td>"}var d,e,f,g,h,k,l,m=this,n=m._id,o=0;for(d=c(),d.push({text:tinymce.translate("No color"),color:"transparent"}),f='<table class="mce-grid mce-grid-border mce-colorbutton-grid" role="list" cellspacing="0"><tbody>',g=d.length-1,k=0;j>k;k++){for(f+="<tr>",h=0;i>h;h++)l=k*i+h,l>g?f+="<td></td>":(e=d[l],f+=b(e.color,e.text));f+="</tr>"}if(a.settings.color_picker_callback){for(f+='<tr><td colspan="'+i+'" class="mce-custom-color-btn"><div id="'+n+'-c" class="mce-widget mce-btn mce-btn-small mce-btn-flat" role="button" tabindex="-1" aria-labelledby="'+n+'-c" style="width: 100%"><button type="button" role="presentation" tabindex="-1">'+tinymce.translate("Custom...")+"</button></div></td></tr>",f+="<tr>",h=0;i>h;h++)f+=b("","Custom color");f+="</tr>"}return f+="</tbody></table>"}function e(b,c){a.focus(),a.formatter.apply(b,{value:c}),a.nodeChanged()}function f(b){a.focus(),a.formatter.remove(b,{value:null},null,!0),a.nodeChanged()}function g(c){function d(a){j.hidePanel(),j.color(a),e(j.settings.format,a)}function g(a,b){a.style.background=b,a.setAttribute("data-mce-color",b)}var h,j=this.parent();if(tinymce.DOM.getParent(c.target,".mce-custom-color-btn")&&(j.hidePanel(),a.settings.color_picker_callback.call(a,function(a){var b,c,e,f=j.panel.getEl().getElementsByTagName("table")[0];for(b=tinymce.map(f.rows[f.rows.length-1].childNodes,function(a){return a.firstChild}),e=0;e<b.length&&(c=b[e],c.getAttribute("data-mce-color"));e++);if(e==i)for(e=0;i-1>e;e++)g(b[e],b[e+1].getAttribute("data-mce-color"));g(c,a),d(a)},b(j.settings.format))),h=c.target.getAttribute("data-mce-color")){if(this.lastId&&document.getElementById(this.lastId).setAttribute("aria-selected",!1),c.target.setAttribute("aria-selected",!0),this.lastId=c.target.id,"transparent"==h)return f(j.settings.format),void j.hidePanel();d(h)}else null!==h&&j.hidePanel()}function h(){var a=this;a._color&&e(a.settings.format,a._color)}var i,j;j=a.settings.textcolor_rows||5,i=a.settings.textcolor_cols||8,a.addButton("forecolor",{type:"colorbutton",tooltip:"Text color",format:"forecolor",panel:{role:"application",ariaRemember:!0,html:d,onclick:g},onclick:h}),a.addButton("backcolor",{type:"colorbutton",tooltip:"Background color",format:"hilitecolor",panel:{role:"application",ariaRemember:!0,html:d,onclick:g},onclick:h})});

View File

@ -0,0 +1,268 @@
/**
* plugin.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('textpattern', function(editor) {
var isPatternsDirty = true, patterns;
patterns = editor.settings.textpattern_patterns || [
{start: '*', end: '*', format: 'italic'},
{start: '**', end: '**', format: 'bold'},
{start: '#', format: 'h1'},
{start: '##', format: 'h2'},
{start: '###', format: 'h3'},
{start: '####', format: 'h4'},
{start: '#####', format: 'h5'},
{start: '######', format: 'h6'},
{start: '1. ', cmd: 'InsertOrderedList'},
{start: '* ', cmd: 'InsertUnorderedList'},
{start: '- ', cmd: 'InsertUnorderedList'}
];
// Returns a sorted patterns list, ordered descending by start length
function getPatterns() {
if (isPatternsDirty) {
patterns.sort(function(a, b) {
if (a.start.length > b.start.length) {
return -1;
}
if (a.start.length < b.start.length) {
return 1;
}
return 0;
});
isPatternsDirty = false;
}
return patterns;
}
// Finds a matching pattern to the specified text
function findPattern(text) {
var patterns = getPatterns();
for (var i = 0; i < patterns.length; i++) {
if (text.indexOf(patterns[i].start) !== 0) {
continue;
}
if (patterns[i].end && text.lastIndexOf(patterns[i].end) != text.length - patterns[i].end.length) {
continue;
}
return patterns[i];
}
}
// Finds the best matching end pattern
function findEndPattern(text, offset, delta) {
var patterns, pattern, i;
// Find best matching end
patterns = getPatterns();
for (i = 0; i < patterns.length; i++) {
pattern = patterns[i];
if (pattern.end && text.substr(offset - pattern.end.length - delta, pattern.end.length) == pattern.end) {
return pattern;
}
}
}
// Handles inline formats like *abc* and **abc**
function applyInlineFormat(space) {
var selection, dom, rng, container, offset, startOffset, text, patternRng, pattern, delta, format;
function splitContainer() {
// Split text node and remove start/end from text node
container = container.splitText(startOffset);
container.splitText(offset - startOffset - delta);
container.deleteData(0, pattern.start.length);
container.deleteData(container.data.length - pattern.end.length, pattern.end.length);
}
selection = editor.selection;
dom = editor.dom;
if (!selection.isCollapsed()) {
return;
}
rng = selection.getRng(true);
container = rng.startContainer;
offset = rng.startOffset;
text = container.data;
delta = space ? 1 : 0;
if (container.nodeType != 3) {
return;
}
// Find best matching end
pattern = findEndPattern(text, offset, delta);
if (!pattern) {
return;
}
// Find start of matched pattern
// TODO: Might need to improve this if there is nested formats
startOffset = Math.max(0, offset - delta);
startOffset = text.lastIndexOf(pattern.start, startOffset - pattern.end.length - 1);
if (startOffset === -1) {
return;
}
// Setup a range for the matching word
patternRng = dom.createRng();
patternRng.setStart(container, startOffset);
patternRng.setEnd(container, offset - delta);
pattern = findPattern(patternRng.toString());
if (!pattern || !pattern.end) {
return;
}
// If container match doesn't have anything between start/end then do nothing
if (container.data.length <= pattern.start.length + pattern.end.length) {
return;
}
format = editor.formatter.get(pattern.format);
if (format && format[0].inline) {
splitContainer();
editor.formatter.apply(pattern.format, {}, container);
return container;
}
}
// Handles block formats like ##abc or 1. abc
function applyBlockFormat() {
var selection, dom, container, firstTextNode, node, format, textBlockElm, pattern, walker, rng, offset;
selection = editor.selection;
dom = editor.dom;
if (!selection.isCollapsed()) {
return;
}
textBlockElm = dom.getParent(selection.getStart(), 'p');
if (textBlockElm) {
walker = new tinymce.dom.TreeWalker(textBlockElm, textBlockElm);
while ((node = walker.next())) {
if (node.nodeType == 3) {
firstTextNode = node;
break;
}
}
if (firstTextNode) {
pattern = findPattern(firstTextNode.data);
if (!pattern) {
return;
}
rng = selection.getRng(true);
container = rng.startContainer;
offset = rng.startOffset;
if (firstTextNode == container) {
offset = Math.max(0, offset - pattern.start.length);
}
if (tinymce.trim(firstTextNode.data).length == pattern.start.length) {
return;
}
if (pattern.format) {
format = editor.formatter.get(pattern.format);
if (format && format[0].block) {
firstTextNode.deleteData(0, pattern.start.length);
editor.formatter.apply(pattern.format, {}, firstTextNode);
rng.setStart(container, offset);
rng.collapse(true);
selection.setRng(rng);
}
}
if (pattern.cmd) {
editor.undoManager.transact(function() {
firstTextNode.deleteData(0, pattern.start.length);
editor.execCommand(pattern.cmd);
});
}
}
}
}
function handleEnter() {
var rng, wrappedTextNode;
wrappedTextNode = applyInlineFormat();
if (wrappedTextNode) {
rng = editor.dom.createRng();
rng.setStart(wrappedTextNode, wrappedTextNode.data.length);
rng.setEnd(wrappedTextNode, wrappedTextNode.data.length);
editor.selection.setRng(rng);
}
applyBlockFormat();
}
function handleSpace() {
var wrappedTextNode, lastChar, lastCharNode, rng, dom;
wrappedTextNode = applyInlineFormat(true);
if (wrappedTextNode) {
dom = editor.dom;
lastChar = wrappedTextNode.data.slice(-1);
// Move space after the newly formatted node
if (/[\u00a0 ]/.test(lastChar)) {
wrappedTextNode.deleteData(wrappedTextNode.data.length - 1, 1);
lastCharNode = dom.doc.createTextNode(lastChar);
if (wrappedTextNode.nextSibling) {
dom.insertAfter(lastCharNode, wrappedTextNode.nextSibling);
} else {
wrappedTextNode.parentNode.appendChild(lastCharNode);
}
rng = dom.createRng();
rng.setStart(lastCharNode, 1);
rng.setEnd(lastCharNode, 1);
editor.selection.setRng(rng);
}
}
}
editor.on('keydown', function(e) {
if (e.keyCode == 13 && !tinymce.util.VK.modifierPressed(e)) {
handleEnter();
}
}, true);
editor.on('keyup', function(e) {
if (e.keyCode == 32 && !tinymce.util.VK.modifierPressed(e)) {
handleSpace();
}
});
this.getPatterns = getPatterns;
this.setPatterns = function(newPatterns) {
patterns = newPatterns;
isPatternsDirty = true;
};
});

View File

@ -0,0 +1 @@
tinymce.PluginManager.add("textpattern",function(a){function b(){return j&&(i.sort(function(a,b){return a.start.length>b.start.length?-1:a.start.length<b.start.length?1:0}),j=!1),i}function c(a){for(var c=b(),d=0;d<c.length;d++)if(0===a.indexOf(c[d].start)&&(!c[d].end||a.lastIndexOf(c[d].end)==a.length-c[d].end.length))return c[d]}function d(a,c,d){var e,f,g;for(e=b(),g=0;g<e.length;g++)if(f=e[g],f.end&&a.substr(c-f.end.length-d,f.end.length)==f.end)return f}function e(b){function e(){i=i.splitText(k),i.splitText(j-k-o),i.deleteData(0,n.start.length),i.deleteData(i.data.length-n.end.length,n.end.length)}var f,g,h,i,j,k,l,m,n,o,p;return f=a.selection,g=a.dom,f.isCollapsed()&&(h=f.getRng(!0),i=h.startContainer,j=h.startOffset,l=i.data,o=b?1:0,3==i.nodeType&&(n=d(l,j,o),n&&(k=Math.max(0,j-o),k=l.lastIndexOf(n.start,k-n.end.length-1),-1!==k&&(m=g.createRng(),m.setStart(i,k),m.setEnd(i,j-o),n=c(m.toString()),n&&n.end&&!(i.data.length<=n.start.length+n.end.length)))))?(p=a.formatter.get(n.format),p&&p[0].inline?(e(),a.formatter.apply(n.format,{},i),i):void 0):void 0}function f(){var b,d,e,f,g,h,i,j,k,l,m;if(b=a.selection,d=a.dom,b.isCollapsed()&&(i=d.getParent(b.getStart(),"p"))){for(k=new tinymce.dom.TreeWalker(i,i);g=k.next();)if(3==g.nodeType){f=g;break}if(f){if(j=c(f.data),!j)return;if(l=b.getRng(!0),e=l.startContainer,m=l.startOffset,f==e&&(m=Math.max(0,m-j.start.length)),tinymce.trim(f.data).length==j.start.length)return;j.format&&(h=a.formatter.get(j.format),h&&h[0].block&&(f.deleteData(0,j.start.length),a.formatter.apply(j.format,{},f),l.setStart(e,m),l.collapse(!0),b.setRng(l))),j.cmd&&a.undoManager.transact(function(){f.deleteData(0,j.start.length),a.execCommand(j.cmd)})}}}function g(){var b,c;c=e(),c&&(b=a.dom.createRng(),b.setStart(c,c.data.length),b.setEnd(c,c.data.length),a.selection.setRng(b)),f()}function h(){var b,c,d,f,g;b=e(!0),b&&(g=a.dom,c=b.data.slice(-1),/[\u00a0 ]/.test(c)&&(b.deleteData(b.data.length-1,1),d=g.doc.createTextNode(c),b.nextSibling?g.insertAfter(d,b.nextSibling):b.parentNode.appendChild(d),f=g.createRng(),f.setStart(d,1),f.setEnd(d,1),a.selection.setRng(f)))}var i,j=!0;i=a.settings.textpattern_patterns||[{start:"*",end:"*",format:"italic"},{start:"**",end:"**",format:"bold"},{start:"#",format:"h1"},{start:"##",format:"h2"},{start:"###",format:"h3"},{start:"####",format:"h4"},{start:"#####",format:"h5"},{start:"######",format:"h6"},{start:"1. ",cmd:"InsertOrderedList"},{start:"* ",cmd:"InsertUnorderedList"},{start:"- ",cmd:"InsertUnorderedList"}],a.on("keydown",function(a){13!=a.keyCode||tinymce.util.VK.modifierPressed(a)||g()},!0),a.on("keyup",function(a){32!=a.keyCode||tinymce.util.VK.modifierPressed(a)||h()}),this.getPatterns=b,this.setPatterns=function(a){i=a,j=!0}});

View File

@ -0,0 +1,135 @@
.mce-visualblocks p {
padding-top: 10px;
border: 1px dashed #BBB;
margin-left: 3px;
background: transparent no-repeat url(data:image/gif;base64,R0lGODlhCQAJAJEAAAAAAP///7u7u////yH5BAEAAAMALAAAAAAJAAkAAAIQnG+CqCN/mlyvsRUpThG6AgA7);
}
.mce-visualblocks h1 {
padding-top: 10px;
border: 1px dashed #BBB;
margin-left: 3px;
background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGu1JuxHoAfRNRW3TWXyF2YiRUAOw==);
}
.mce-visualblocks h2 {
padding-top: 10px;
border: 1px dashed #BBB;
margin-left: 3px;
background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8Hybbx4oOuqgTynJd6bGlWg3DkJzoaUAAAOw==);
}
.mce-visualblocks h3 {
padding-top: 10px;
border: 1px dashed #BBB;
margin-left: 3px;
background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIZjI8Hybbx4oOuqgTynJf2Ln2NOHpQpmhAAQA7);
}
.mce-visualblocks h4 {
padding-top: 10px;
border: 1px dashed #BBB;
margin-left: 3px;
background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxInR0zqeAdhtJlXwV1oCll2HaWgAAOw==);
}
.mce-visualblocks h5 {
padding-top: 10px;
border: 1px dashed #BBB;
margin-left: 3px;
background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjane4iq5GlW05GgIkIZUAAAOw==);
}
.mce-visualblocks h6 {
padding-top: 10px;
border: 1px dashed #BBB;
margin-left: 3px;
background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDgAKAIABALu7u////yH5BAEAAAEALAAAAAAOAAoAAAIajI8HybbxIoiuwjan04jep1iZ1XRlAo5bVgAAOw==);
}
.mce-visualblocks div {
padding-top: 10px;
border: 1px dashed #BBB;
margin-left: 3px;
background: transparent no-repeat url(data:image/gif;base64,R0lGODlhEgAKAIABALu7u////yH5BAEAAAEALAAAAAASAAoAAAIfjI9poI0cgDywrhuxfbrzDEbQM2Ei5aRjmoySW4pAAQA7);
}
.mce-visualblocks section {
padding-top: 10px;
border: 1px dashed #BBB;
margin: 0 0 1em 3px;
background: transparent no-repeat url(data:image/gif;base64,R0lGODlhKAAKAIABALu7u////yH5BAEAAAEALAAAAAAoAAoAAAI5jI+pywcNY3sBWHdNrplytD2ellDeSVbp+GmWqaDqDMepc8t17Y4vBsK5hDyJMcI6KkuYU+jpjLoKADs=);
}
.mce-visualblocks article {
padding-top: 10px;
border: 1px dashed #BBB;
margin: 0 0 1em 3px;
background: transparent no-repeat url(data:image/gif;base64,R0lGODlhKgAKAIABALu7u////yH5BAEAAAEALAAAAAAqAAoAAAI6jI+pywkNY3wG0GBvrsd2tXGYSGnfiF7ikpXemTpOiJScasYoDJJrjsG9gkCJ0ag6KhmaIe3pjDYBBQA7);
}
.mce-visualblocks blockquote {
padding-top: 10px;
border: 1px dashed #BBB;
background: transparent no-repeat url(data:image/gif;base64,R0lGODlhPgAKAIABALu7u////yH5BAEAAAEALAAAAAA+AAoAAAJPjI+py+0Knpz0xQDyuUhvfoGgIX5iSKZYgq5uNL5q69asZ8s5rrf0yZmpNkJZzFesBTu8TOlDVAabUyatguVhWduud3EyiUk45xhTTgMBBQA7);
}
.mce-visualblocks address {
padding-top: 10px;
border: 1px dashed #BBB;
margin: 0 0 1em 3px;
background: transparent no-repeat url(data:image/gif;base64,R0lGODlhLQAKAIABALu7u////yH5BAEAAAEALAAAAAAtAAoAAAI/jI+pywwNozSP1gDyyZcjb3UaRpXkWaXmZW4OqKLhBmLs+K263DkJK7OJeifh7FicKD9A1/IpGdKkyFpNmCkAADs=);
}
.mce-visualblocks pre {
padding-top: 10px;
border: 1px dashed #BBB;
margin-left: 3px;
background: transparent no-repeat url(data:image/gif;base64,R0lGODlhFQAKAIABALu7uwAAACH5BAEAAAEALAAAAAAVAAoAAAIjjI+ZoN0cgDwSmnpz1NCueYERhnibZVKLNnbOq8IvKpJtVQAAOw==);
}
.mce-visualblocks figure {
padding-top: 10px;
border: 1px dashed #BBB;
margin: 0 0 1em 3px;
background: transparent no-repeat url(data:image/gif;base64,R0lGODlhJAAKAIAAALu7u////yH5BAEAAAEALAAAAAAkAAoAAAI0jI+py+2fwAHUSFvD3RlvG4HIp4nX5JFSpnZUJ6LlrM52OE7uSWosBHScgkSZj7dDKnWAAgA7);
}
.mce-visualblocks hgroup {
padding-top: 10px;
border: 1px dashed #BBB;
margin: 0 0 1em 3px;
background: transparent no-repeat url(data:image/gif;base64,R0lGODlhJwAKAIABALu7uwAAACH5BAEAAAEALAAAAAAnAAoAAAI3jI+pywYNI3uB0gpsRtt5fFnfNZaVSYJil4Wo03Hv6Z62uOCgiXH1kZIIJ8NiIxRrAZNMZAtQAAA7);
}
.mce-visualblocks aside {
padding-top: 10px;
border: 1px dashed #BBB;
margin: 0 0 1em 3px;
background: transparent no-repeat url(data:image/gif;base64,R0lGODlhHgAKAIABAKqqqv///yH5BAEAAAEALAAAAAAeAAoAAAItjI+pG8APjZOTzgtqy7I3f1yehmQcFY4WKZbqByutmW4aHUd6vfcVbgudgpYCADs=);
}
.mce-visualblocks figcaption {
border: 1px dashed #BBB;
}
.mce-visualblocks ul {
padding-top: 10px;
border: 1px dashed #BBB;
margin: 0 0 1em 3px;
background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDQAKAIAAALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybGuYnqUVSjvw26DzzXiqIDlVwAAOw==)
}
.mce-visualblocks ol {
padding-top: 10px;
border: 1px dashed #BBB;
margin: 0 0 1em 3px;
background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybH6HHt0qourxC6CvzXieHyeWQAAOw==);
}
.mce-visualblocks dl {
padding-top: 10px;
border: 1px dashed #BBB;
margin: 0 0 1em 3px;
background: transparent no-repeat url(data:image/gif;base64,R0lGODlhDQAKAIABALu7u////yH5BAEAAAEALAAAAAANAAoAAAIXjI8GybEOnmOvUoWznTqeuEjNSCqeGRUAOw==);
}

View File

@ -0,0 +1,86 @@
/**
* plugin.js
*
* Copyright 2012, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/*global tinymce:true */
tinymce.PluginManager.add('visualblocks', function(editor, url) {
var cssId, visualBlocksMenuItem, enabled;
// We don't support older browsers like IE6/7 and they don't provide prototypes for DOM objects
if (!window.NodeList) {
return;
}
function toggleActiveState() {
var self = this;
self.active(enabled);
editor.on('VisualBlocks', function() {
self.active(editor.dom.hasClass(editor.getBody(), 'mce-visualblocks'));
});
}
editor.addCommand('mceVisualBlocks', function() {
var dom = editor.dom, linkElm;
if (!cssId) {
cssId = dom.uniqueId();
linkElm = dom.create('link', {
id: cssId,
rel: 'stylesheet',
href: url + '/css/visualblocks.css'
});
editor.getDoc().getElementsByTagName('head')[0].appendChild(linkElm);
}
// Toggle on/off visual blocks while computing previews
editor.on("PreviewFormats AfterPreviewFormats", function(e) {
if (enabled) {
dom.toggleClass(editor.getBody(), 'mce-visualblocks', e.type == "afterpreviewformats");
}
});
dom.toggleClass(editor.getBody(), 'mce-visualblocks');
enabled = editor.dom.hasClass(editor.getBody(), 'mce-visualblocks');
if (visualBlocksMenuItem) {
visualBlocksMenuItem.active(dom.hasClass(editor.getBody(), 'mce-visualblocks'));
}
editor.fire('VisualBlocks');
});
editor.addButton('visualblocks', {
title: 'Show blocks',
cmd: 'mceVisualBlocks',
onPostRender: toggleActiveState
});
editor.addMenuItem('visualblocks', {
text: 'Show blocks',
cmd: 'mceVisualBlocks',
onPostRender: toggleActiveState,
selectable: true,
context: 'view',
prependToContext: true
});
editor.on('init', function() {
if (editor.settings.visualblocks_default_state) {
editor.execCommand('mceVisualBlocks', false, null, {skip_focus: true});
}
});
editor.on('remove', function() {
editor.dom.removeClass(editor.getBody(), 'mce-visualblocks');
});
});

Some files were not shown because too many files have changed in this diff Show More