Files
Umbraco-CMS/components/editorControls/tinyMCE3/TinyMCE.cs
Shandem f6d0d043b5 DO NOT DOWNLOAD. DOWNLOAT LATEST STABLE FROM RELEASE TAB
Created 4.1.0 branch

[TFS Changeset #55082]
2009-06-19 07:39:16 +00:00

586 lines
24 KiB
C#

using System;
using System.Collections;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.UI;
using umbraco.BasePages;
using umbraco.BusinessLogic;
using umbraco.cms.businesslogic.web;
using umbraco.editorControls.wysiwyg;
using umbraco.interfaces;
using umbraco.uicontrols;
using umbraco.editorControls.tinymce;
namespace umbraco.editorControls.tinyMCE3 {
public class TinyMCE : webcontrol.TinyMCEWebControl , IDataEditor, IMenuElement, ILiveEditingDataEditor {
private IData _data;
private bool m_isInLiveEditingMode = false;
private bool _enableContextMenu = false;
private string _editorButtons = "";
private string _advancedUsers = "";
private bool _fullWidth = false;
private int _width = 0;
private int _height = 0;
private bool _showLabel = false;
private string _plugins = "";
private ArrayList _stylesheets = new ArrayList();
private ArrayList _menuIcons = new ArrayList();
private SortedList _buttons = new SortedList();
private SortedList _mceButtons = new SortedList();
private bool _isInitialized = false;
private string _activateButtons = "";
private string _disableButtons = "help,visualaid,";
private int m_maxImageWidth = 500;
public virtual string Plugins {
get { return _plugins; }
set { _plugins = value; }
}
public TinyMCE(IData Data, string Configuration) {
_data = Data;
try
{
string[] configSettings = Configuration.Split("|".ToCharArray());
if (configSettings.Length > 0)
{
_editorButtons = configSettings[0];
if (configSettings.Length > 1)
if (configSettings[1] == "1")
_enableContextMenu = true;
if (configSettings.Length > 2)
_advancedUsers = configSettings[2];
if (configSettings.Length > 3)
{
if (configSettings[3] == "1")
_fullWidth = true;
else if (configSettings[4].Split(',').Length > 1)
{
_width = int.Parse(configSettings[4].Split(',')[0]);
_height = int.Parse(configSettings[4].Split(',')[1]);
}
}
// default width/height
if (_width < 1)
_width = 500;
if (_height < 1)
_height = 400;
// add stylesheets
if (configSettings.Length > 4)
{
foreach (string s in configSettings[5].Split(",".ToCharArray()))
_stylesheets.Add(s);
}
if (configSettings.Length > 6 && configSettings[6] != "")
_showLabel = bool.Parse(configSettings[6]);
if (configSettings.Length > 7 && configSettings[7] != "")
m_maxImageWidth = int.Parse(configSettings[7].ToString());
// sizing
if (!_fullWidth)
{
config.Add("width", _width.ToString());
config.Add("height", _height.ToString());
}
if (_enableContextMenu)
_plugins += ",contextmenu";
// safari compatibility
if (HttpContext.Current.Request.Browser.Browser.ToLower().Contains("safari"))
{
_plugins += ",safari";
}
// If the editor is used in umbraco, use umbraco's own toolbar
bool onFront = false;
if (GlobalSettings.RequestIsInUmbracoApplication(HttpContext.Current) || umbraco.presentation.UmbracoContext.Current.LiveEditingContext.Enabled)
{
config.Add("theme_umbraco_toolbar_location", "external");
config.Add("skin", "umbraco");
config.Add("inlinepopups_skin ", "umbraco");
}
else
{
onFront = true;
config.Add("theme_umbraco_toolbar_location", "top");
}
// load plugins
IDictionaryEnumerator pluginEnum = umbraco.editorControls.tinymce.tinyMCEConfiguration.Plugins.GetEnumerator();
while (pluginEnum.MoveNext())
{
umbraco.editorControls.tinymce.tinyMCEPlugin plugin = (umbraco.editorControls.tinymce.tinyMCEPlugin)pluginEnum.Value;
if (plugin.UseOnFrontend || (!onFront && !plugin.UseOnFrontend))
_plugins += "," + plugin.Name;
}
if (_plugins.StartsWith(","))
_plugins = _plugins.Substring(1, _plugins.Length - 1);
if (_plugins.EndsWith(","))
_plugins = _plugins.Substring(0, _plugins.Length - 1);
config.Add("plugins", _plugins);
// Check advanced settings
if (("," + _advancedUsers + ",").IndexOf("," + UmbracoEnsuredPage.CurrentUser.UserType.Id + ",") > -1)
config.Add("umbraco_advancedMode", "true");
else
config.Add("umbraco_advancedMode", "false");
// Check maximum image width
config.Add("umbraco_maximumDefaultImageWidth", m_maxImageWidth.ToString());
// Styles
string cssFiles = String.Empty;
string styles = string.Empty;
foreach (string styleSheetId in _stylesheets)
{
if (styleSheetId.Trim() != "")
try
{
StyleSheet s = new StyleSheet(int.Parse(styleSheetId));
if (s.nodeObjectType == StyleSheet.ModuleObjectType)
{
cssFiles += GlobalSettings.Path + "/../css/" + s.Text + ".css";
foreach (StylesheetProperty p in s.Properties)
{
if (styles != string.Empty)
{
styles += ";";
}
if (p.Alias.StartsWith("."))
styles += p.Text + "=" + p.Alias;
else
styles += p.Text + "=" + p.Alias;
}
cssFiles += ",";
}
}
catch (Exception ee)
{
Log.Add(LogTypes.Error, -1,
string.Format(
string.Format("Error adding stylesheet to tinymce (id: {{0}}). {0}", ee),
styleSheetId));
}
}
// remove any ending comma (,)
if (!string.IsNullOrEmpty(cssFiles))
{
cssFiles = cssFiles.TrimEnd(',');
}
// language
config.Add("language", User.GetCurrent().Language);
config.Add("content_css", cssFiles);
config.Add("theme_umbraco_styles", styles);
// Add buttons
IDictionaryEnumerator ide = umbraco.editorControls.tinymce.tinyMCEConfiguration.Commands.GetEnumerator();
while (ide.MoveNext())
{
umbraco.editorControls.tinymce.tinyMCECommand cmd = (umbraco.editorControls.tinymce.tinyMCECommand)ide.Value;
if (_editorButtons.IndexOf("," + cmd.Alias + ",") > -1)
_activateButtons += cmd.Alias + ",";
else
_disableButtons += cmd.Alias + ",";
}
if (_activateButtons.Length > 0)
_activateButtons = _activateButtons.Substring(0, _activateButtons.Length - 1);
if (_disableButtons.Length > 0)
_disableButtons = _disableButtons.Substring(0, _disableButtons.Length - 1);
// Add buttons
initButtons();
_activateButtons = "";
int separatorPriority = 0;
ide = _mceButtons.GetEnumerator();
while (ide.MoveNext())
{
string mceCommand = ide.Value.ToString();
int curPriority = (int)ide.Key;
// Check priority
if (separatorPriority > 0 &&
Math.Floor(decimal.Parse(curPriority.ToString()) / 10) >
Math.Floor(decimal.Parse(separatorPriority.ToString()) / 10))
_activateButtons += "separator,";
_activateButtons += mceCommand + ",";
separatorPriority = curPriority;
}
config.Add("theme_umbraco_buttons1", _activateButtons);
config.Add("theme_umbraco_buttons2", "");
config.Add("theme_umbraco_buttons3", "");
config.Add("theme_umbraco_toolbar_align", "left");
config.Add("theme_umbraco_disable", _disableButtons);
config.Add("theme_umbraco_path ", "true");
config.Add("extended_valid_elements", "div[*]");
config.Add("document_base_url", "/");
config.Add("relative_urls", "false");
config.Add("remove_script_host", "true");
config.Add("event_elements", "div");
config.Add("paste_auto_cleanup_on_paste", "true");
config.Add("valid_elements", tinyMCEConfiguration.ValidElements.Substring(1, tinyMCEConfiguration.ValidElements.Length-2));
config.Add("invalid_elements", tinyMCEConfiguration.InvalidElements);
// custom commands
if (tinyMCEConfiguration.ConfigOptions.Count > 0)
{
ide = tinyMCEConfiguration.ConfigOptions.GetEnumerator();
while (ide.MoveNext())
{
config.Add(ide.Key.ToString(), ide.Value.ToString());
}
}
//if (HttpContext.Current.Request.Path.IndexOf(GlobalSettings.Path) > -1)
// config.Add("language", User.GetUser(BasePage.GetUserId(BasePage.umbracoUserContextID)).Language);
//else
// config.Add("language", System.Threading.Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName);
if (_fullWidth)
{
config.Add("auto_resize", "true");
base.Columns = 30;
base.Rows = 30;
}
else
{
base.Columns = 0;
base.Rows = 0;
}
EnableViewState = false;
}
}
catch (Exception ex)
{
throw new ArgumentException("Incorrect TinyMCE configuration.", "Configuration", ex);
}
}
#region IDataEditor Members
#region TreatAsRichTextEditor
public virtual bool TreatAsRichTextEditor {
get { return false; }
}
#endregion
#region ShowLabel
public virtual bool ShowLabel {
get { return _showLabel; }
}
#endregion
#region Editor
public Control Editor {
get { return this; }
}
#endregion
#region Save()
public virtual void Save() {
string parsedString = base.Text.Trim();
if (parsedString != string.Empty) {
parsedString = replaceMacroTags(parsedString).Trim();
// clean macros and add paragraph element for tidy
bool removeParagraphs = false;
if (parsedString.Length > 16 && parsedString.ToLower().Substring(0, 17) == "|||?umbraco_macro") {
removeParagraphs = true;
parsedString = "<p>" + parsedString + "</p>";
}
// tidy html
if (UmbracoSettings.TidyEditorContent) {
string tidyTxt = library.Tidy(parsedString, false);
if (tidyTxt != "[error]") {
// compensate for breaking macro tags by tidy
parsedString = tidyTxt.Replace("/?>", "/>");
if (removeParagraphs) {
if (parsedString.Length - parsedString.Replace("<", "").Length == 2)
parsedString = parsedString.Replace("<p>", "").Replace("</p>", "");
}
} else {
// TODO
// How to log errors? _data.NodeId does not exist?
//BusinessLogic.Log.Add(BusinessLogic.LogTypes.Error, BusinessLogic.User.GetUser(0), _data.NodeId, "Error tidying txt from property: " + _data.PropertyId.ToString());
}
}
// rescue umbraco tags
parsedString = parsedString.Replace("|||?", "<?").Replace("/|||", "/>").Replace("|*|", "\"");
// fix images
parsedString = umbraco.editorControls.tinymce.tinyMCEImageHelper.cleanImages(parsedString);
// parse current domain and instances of slash before anchor (to fix anchor bug)
// NH 31-08-2007
if (HttpContext.Current.Request.ServerVariables != null) {
parsedString = parsedString.Replace(helper.GetBaseUrl(HttpContext.Current) + "/#", "#");
parsedString = parsedString.Replace(helper.GetBaseUrl(HttpContext.Current), "");
}
// if text is an empty parargraph, make it all empty
if (parsedString.ToLower() == "<p></p>")
parsedString = "";
}
_data.Value = parsedString;
// update internal webcontrol value with parsed result
base.Text = parsedString;
}
#endregion
protected override void OnLoad(EventArgs e) {
try {
// add current page info
base.NodeId = ((cms.businesslogic.datatype.DefaultData)_data).NodeId;
base.VersionId = ((cms.businesslogic.datatype.DefaultData)_data).Version;
config.Add("theme_umbraco_pageId", base.NodeId.ToString());
config.Add("theme_umbraco_versionId", base.VersionId.ToString());
// we'll need to make an extra check for the liveediting as that value is set after the constructor have initialized
if (IsInLiveEditingMode)
{
if (config["theme_umbraco_toolbar_location"] == null)
config.Add("theme_umbraco_toolbar_location", "");
config["theme_umbraco_toolbar_location"] = "external";
config.Add("umbraco_toolbar_id",
"LiveEditingClientToolbar");
}
else {
config.Add("umbraco_toolbar_id",
ElementIdPreFix + ((cms.businesslogic.datatype.DefaultData)_data).PropertyId.ToString());
}
} catch {
// Empty catch as this is caused by the document doesn't exists yet,
// like when using this on an autoform
}
base.OnLoad(e);
}
protected override void OnInit(EventArgs e) {
base.OnInit(e);
if (_data != null && _data.Value != null)
base.Text = _data.Value.ToString();
}
private string replaceMacroTags(string text) {
while (findStartTag(text) > -1) {
string result = text.Substring(findStartTag(text), findEndTag(text) - findStartTag(text));
text = text.Replace(result, generateMacroTag(result));
}
return text;
}
private string generateMacroTag(string macroContent) {
string macroAttr = macroContent.Substring(5, macroContent.IndexOf(">") - 5);
string macroTag = "|||?UMBRACO_MACRO ";
Hashtable attributes = ReturnAttributes(macroAttr);
IDictionaryEnumerator ide = attributes.GetEnumerator();
while (ide.MoveNext()) {
if (ide.Key.ToString().IndexOf("umb_") != -1) {
// Hack to compensate for Firefox adding all attributes as lowercase
string orgKey = ide.Key.ToString();
if (orgKey == "umb_macroalias")
orgKey = "umb_macroAlias";
macroTag += orgKey.Substring(4, orgKey.ToString().Length - 4) + "=|*|" +
ide.Value.ToString() + "|*| ";
}
}
macroTag += "/|||";
return macroTag;
}
public static Hashtable ReturnAttributes(String tag) {
Hashtable ht = new Hashtable();
MatchCollection m =
Regex.Matches(tag, "(?<attributeName>\\S*)=\"(?<attributeValue>[^\"]*)\"",
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
foreach (Match attributeSet in m)
ht.Add(attributeSet.Groups["attributeName"].Value.ToString(),
attributeSet.Groups["attributeValue"].Value.ToString());
return ht;
}
private int findStartTag(string text) {
string temp = "";
text = text.ToLower();
if (text.IndexOf("ismacro=\"true\"") > -1) {
temp = text.Substring(0, text.IndexOf("ismacro=\"true\""));
return temp.LastIndexOf("<");
}
return -1;
}
private int findEndTag(string text) {
string find = "<!-- endumbmacro -->";
int endMacroIndex = text.ToLower().IndexOf(find);
string tempText = text.ToLower().Substring(endMacroIndex + find.Length, text.Length - endMacroIndex - find.Length);
int finalEndPos = 0;
while (tempText.Length > 5)
if (tempText.Substring(finalEndPos, 6) == "</div>")
break;
else
finalEndPos++;
return endMacroIndex + find.Length + finalEndPos + 6;
}
#endregion
#region IDataFieldWithButtons Members
public object[] MenuIcons {
get {
initButtons();
object[] tempIcons = new object[_menuIcons.Count];
for (int i = 0; i < _menuIcons.Count; i++)
tempIcons[i] = _menuIcons[i];
return tempIcons;
}
}
private void initButtons() {
if (!_isInitialized) {
_isInitialized = true;
// Add icons for the editor control:
// Html
// Preview
// Style picker, showstyles
// Bold, italic, Text Gen
// Align: left, center, right
// Lists: Bullet, Ordered, indent, undo indent
// Link, Anchor
// Insert: Image, macro, table, formular
foreach (string button in _activateButtons.Split(',')) {
if (button.Trim() != "") {
try {
umbraco.editorControls.tinymce.tinyMCECommand cmd = (umbraco.editorControls.tinymce.tinyMCECommand)umbraco.editorControls.tinymce.tinyMCEConfiguration.Commands[button];
string appendValue = "";
if (cmd.Value != "")
appendValue = ", '" + cmd.Value + "'";
_mceButtons.Add(cmd.Priority, cmd.Command);
_buttons.Add(cmd.Priority,
new editorButton(cmd.Alias, ui.Text("buttons", cmd.Alias, null), cmd.Icon,
"tinyMCE.execInstanceCommand('" + ClientID + "', '" +
cmd.Command + "', " + cmd.UserInterface + appendValue + ")"));
} catch (Exception ee) {
Log.Add(LogTypes.Error, User.GetUser(0), -1,
string.Format("TinyMCE: Error initializing button '{0}': {1}", button, ee.ToString()));
}
}
}
// add save icon
int separatorPriority = 0;
IDictionaryEnumerator ide = _buttons.GetEnumerator();
while (ide.MoveNext()) {
object buttonObj = ide.Value;
int curPriority = (int)ide.Key;
// Check priority
if (separatorPriority > 0 &&
Math.Floor(decimal.Parse(curPriority.ToString()) / 10) >
Math.Floor(decimal.Parse(separatorPriority.ToString()) / 10))
_menuIcons.Add("|");
try {
editorButton e = (editorButton)buttonObj;
MenuIconI menuItem = new MenuIconClass();
menuItem.OnClickCommand = e.onClickCommand;
menuItem.ImageURL = e.imageUrl;
menuItem.AltText = e.alttag;
menuItem.ID = e.id;
_menuIcons.Add(menuItem);
} catch {
}
separatorPriority = curPriority;
}
}
}
#endregion
#region IMenuElement Members
public string ElementName {
get { return "div"; }
}
public string ElementIdPreFix {
get { return "umbTinymceMenu"; }
}
public string ElementClass {
get { return "tinymceMenuBar"; }
}
public int ExtraMenuWidth {
get {
initButtons();
return _buttons.Count * 40 + 300;
}
}
#endregion
#region ILiveEditingDataEditor Members
public Control LiveEditingControl
{
get {
m_isInLiveEditingMode = true;
base.IsInLiveEditingMode = true;
return this;
}
}
#endregion
}
}