示例#1
0
        /// <summary>
        /// Renders the base control.
        /// </summary>
        /// <param name="writer">The writer.</param>
        public void RenderBaseControl(HtmlTextWriter writer)
        {
            int editorHeight = EditorHeight.AsIntegerOrNull() ?? 200;

            // Add merge field help
            if (MergeFields.Any())
            {
                writer.Write("<div class='codeeditor-header margin-b-md clearfix'>");
                _mfpMergeFields.RenderControl(writer);
                writer.Write("</div>");

                editorHeight = editorHeight - 40;
            }

            // add editor div
            string customDiv = @"<div class='code-editor-container' style='position:relative; height: {0}px'><pre id='codeeditor-div-{1}'>{2}</pre></div>";

            writer.Write(string.Format(customDiv, editorHeight, this.ClientID, HttpUtility.HtmlEncode(this.Text)));

            // write custom css for the code editor
            string customStyle = @"
                <style type='text/css' media='screen'>
                    #codeeditor-div-{0} {{ 
                        position: absolute;
                        top: 0;
                        right: 0;
                        bottom: 0;
                        left: 0;
                    }}      
                </style>     
";
            string cssCode     = string.Format(customStyle, this.ClientID);

            writer.Write(cssCode);

            // make textbox hidden
            ((WebControl)this).Style.Add(HtmlTextWriterStyle.Display, "none");

            // add ace.js on demand only when there will be a codeeditor rendered
            if (ScriptManager.GetCurrent(this.Page).IsInAsyncPostBack)
            {
                ScriptManager.RegisterClientScriptInclude(this.Page, this.Page.GetType(), "ace-include", ResolveUrl("~/Scripts/ace/ace.js"));
            }

            string scriptFormat = @"
                var ce_{0} = ace.edit('codeeditor-div-{0}');
                ce_{0}.setTheme('ace/theme/{1}');
                ce_{0}.getSession().setMode('ace/mode/{2}');
                ce_{0}.setShowPrintMargin(false);

                document.getElementById('{0}').value = $('<div/>').text( ce_{0}.getValue() ).html().replace(/&#39/g,""&apos"");
                ce_{0}.getSession().on('change', function(e) {{
                    document.getElementById('{0}').value = $('<div/>').text( ce_{0}.getValue() ).html().replace(/&#39/g,""&apos"");
                    {3}
                }});
";

            string script = string.Format(scriptFormat, this.ClientID, EditorThemeAsString(this.EditorTheme), EditorModeAsString(this.EditorMode), this.OnChangeScript);

            ScriptManager.RegisterStartupScript(this, this.GetType(), "codeeditor_" + this.ClientID, script, true);

            base.RenderControl(writer);
        }
示例#2
0
        /// <summary>
        /// Renders the base control.
        /// </summary>
        /// <param name="writer">The writer.</param>
        public void RenderBaseControl(HtmlTextWriter writer)
        {
            bool rockMergeFieldEnabled   = MergeFields.Any();
            bool rockFileBrowserEnabled  = false;
            bool rockAssetManagerEnabled = false;
            var  currentPerson           = this.RockBlock().CurrentPerson;

            // only show the File/Image plugin if they have Auth to the file browser page
            var fileBrowserPage = new Rock.Model.PageService(new RockContext()).Get(Rock.SystemGuid.Page.HTMLEDITOR_ROCKFILEBROWSER_PLUGIN_FRAME.AsGuid());

            if (fileBrowserPage != null && currentPerson != null)
            {
                rockFileBrowserEnabled = fileBrowserPage.IsAuthorized(Authorization.VIEW, currentPerson);
            }

            var assetManagerPage = new Rock.Model.PageService(new RockContext()).Get(Rock.SystemGuid.Page.HTMLEDITOR_ROCKASSETMANAGER_PLUGIN_FRAME.AsGuid());

            if (assetManagerPage != null && currentPerson != null)
            {
                rockAssetManagerEnabled = assetManagerPage.IsAuthorized(Authorization.VIEW, currentPerson);
            }

            string documentFolderRoot = this.DocumentFolderRoot;
            string imageFolderRoot    = this.ImageFolderRoot;

            if (this.UserSpecificRoot)
            {
                var currentUser = this.RockBlock().CurrentUser;
                if (currentUser != null)
                {
                    documentFolderRoot = System.Web.VirtualPathUtility.Combine(documentFolderRoot.EnsureTrailingBackslash(), currentUser.UserName.ToString());
                    imageFolderRoot    = System.Web.VirtualPathUtility.Combine(imageFolderRoot.EnsureTrailingBackslash(), currentUser.UserName.ToString());
                }
            }

            string callbacksOption = string.Empty;

            if (!string.IsNullOrEmpty(this.CallbackOnKeyupScript) || !string.IsNullOrEmpty(this.CallbackOnChangeScript))
            {
                callbacksOption =
                    $@"
onKeyup: function(e) {{
    {this.CallbackOnKeyupScript}
}},
onChange: function(contents, $editable) {{
    {this.CallbackOnChangeScript}
}}
";
            }


            string summernoteInitScript = $@"
function pageLoad() {{
  // remove any leftover popovers that summernote might have created and orphaned
  $('.note-popover.popover').hide();
}}

$(document).ready( function() {{

    var summerNoteEditor_{this.ClientID} = $('#{this.ClientID}').summernote({{
        height: '{this.Height}', //set editable area's height
        toolbar: Rock.htmlEditor.toolbar_RockCustomConfig{this.Toolbar.ConvertToString()},

        popover: {{
          image: [
            ['custom1', ['rockimagelink']],
            ['imagesize', ['resizeFull', 'resizeHalf', 'resizeQuarter']],
            ['custom2', ['rockimagebrowser', 'rockassetmanager']],
            ['float', ['floatLeft', 'floatRight', 'floatNone']],
            ['remove', ['removeMedia']]
          ],
          link: [
            ['link', ['linkDialogShow', 'unlink']]
          ],
          air: [
            ['color', ['color']],
            ['font', ['bold', 'underline', 'clear']],
            ['para', ['ul', 'paragraph']],
            ['table', ['table']],
            ['insert', ['link', 'picture']]
          ]
        }},
        callbacks: {{
            onInit: function() {{
                $(this).parent().removeClass('loading').css('min-height', '');
            }},
           {callbacksOption}
        }},

        buttons: {{
            rockfilebrowser: RockFileBrowser,
            rockimagebrowser: RockImageBrowser,
            rockimagelink: RockImageLink,
            rockassetmanager: RockAssetManager,
            rockmergefield: RockMergeField,
            rockcodeeditor: RockCodeEditor,
            rockpastetext: RockPasteText,
            rockpastefromword: RockPasteFromWord
        }},

        rockFileBrowserOptions: {{
            enabled: {rockFileBrowserEnabled.ToTrueFalse().ToLower()},
            documentFolderRoot: '{Rock.Security.Encryption.EncryptString( documentFolderRoot )}',
            imageFolderRoot: '{Rock.Security.Encryption.EncryptString( imageFolderRoot )}'
        }},

        rockAssetManagerOptions: {{
            enabled: { rockAssetManagerEnabled.ToTrueFalse().ToLower() }
        }},

        rockMergeFieldOptions: {{
            enabled: {rockMergeFieldEnabled.ToTrueFalse().ToLower()},
            mergeFields: '{this.MergeFields.AsDelimited( "," )}'
        }},
        rockTheme: '{( ( RockPage ) this.Page ).Site.Theme}',

        codeEditorOptions: {{
            controlId: '{_ceEditor.ClientID}',
            inCodeEditorModeHiddenFieldId: '{_hfInCodeEditorMode.ClientID}'
        }},

        disableDragAndDrop: true,
    }});

    if ({StartInCodeEditorMode.ToTrueFalse().ToLower()} && RockCodeEditor) {{
        RockCodeEditor(summerNoteEditor_{this.ClientID}.data('summernote'), true).trigger('click');
    }}

}});
";

            ScriptManager.RegisterStartupScript(this, this.GetType(), "summernote_init_script_" + this.ClientID, summernoteInitScript, true);

            // add script on demand only when there will be an htmleditor rendered
            if (ScriptManager.GetCurrent(this.Page).IsInAsyncPostBack)
            {
                ScriptManager.RegisterClientScriptInclude(this.Page, this.Page.GetType(), "summernote-lib", ((RockPage)this.Page).ResolveRockUrl("~/Scripts/summernote/summernote.js", true));
                var bundleUrl = System.Web.Optimization.BundleResolver.Current.GetBundleUrl("~/Scripts/Bundles/RockHtmlEditorPlugins");
                ScriptManager.RegisterClientScriptInclude(this.Page, this.Page.GetType(), "summernote-plugins", bundleUrl);
            }

            // set this textbox hidden until we can run the js to attach summernote to it
            this.Style[HtmlTextWriterStyle.Display] = "none";

            writer.AddAttribute("class", "html-editor-container loading");
            writer.AddStyleAttribute("min-height", this.Height.ToString());
            writer.RenderBeginTag(HtmlTextWriterTag.Div);

            base.RenderControl(writer);

            writer.RenderEndTag();
        }
示例#3
0
        /// <summary>
        /// Renders the base control.
        /// </summary>
        /// <param name="writer">The writer.</param>
        public void RenderBaseControl(HtmlTextWriter writer)
        {
            int editorHeight = EditorHeight.AsIntegerOrNull() ?? 200;

            // Add merge field help
            if (MergeFields.Any())
            {
                writer.Write("<div class='codeeditor-header margin-b-md clearfix'>");
                _mfpMergeFields.RenderControl(writer);
                writer.Write("</div>");

                editorHeight = editorHeight - 40;
            }

            // add editor div
            var    encodedText = HttpUtility.HtmlEncode(this.Text);
            string customDiv   = $@"<div class='code-editor-container {this.CssClass}' style='position:relative; height: {editorHeight}px'><pre id='codeeditor-div-{this.ClientID}'>{encodedText}</pre></div>";

            writer.Write(customDiv);

            // write custom css for the code editor
            string styleTag = $@"
                <style type='text/css' media='screen'>
                    #codeeditor-div-{this.ClientID} {{
                        position: absolute;
                        top: 0;
                        right: 0;
                        bottom: 0;
                        left: 0;
                    }}
                </style>
";

            writer.Write(styleTag);

            // make textbox hidden
            ((WebControl)this).Style.Add(HtmlTextWriterStyle.Display, "none");

            // add ace.js on demand only when there will be a codeeditor rendered
            if (ScriptManager.GetCurrent(this.Page).IsInAsyncPostBack)
            {
                ScriptManager.RegisterClientScriptInclude(this.Page, this.Page.GetType(), "ace-include", ResolveUrl("~/Scripts/ace/ace.js"));
            }

            string scriptFormat = @"
                var ce_{0} = ace.edit('codeeditor-div-{0}');
                ce_{0}.setTheme('ace/theme/{1}');
                ce_{0}.getSession().setMode('ace/mode/{2}');
                ce_{0}.getSession().setUseWrapMode({7});
                ce_{0}.setShowPrintMargin(false);
                ce_{0}.commands.addCommand({{
                    name: 'Toggle Fullscreen',
                    bindKey: 'F11',
                    exec: function(editor) {{
                        Rock.controls.fullScreen.toggleFullscreen(editor.container);
                        editor.resize()
                    }}
                }});
                $('#codeeditor-div-{0}').data('aceEditor', ce_{0});

                document.getElementById('{0}').value = $('<div/>').text( ce_{0}.getValue() ).html().replace(/&#39/g,""&apos"");
                ce_{0}.getSession().on('change', function(e) {{

                    // get the raw content from the codeEditor
                    var contents = ce_{0}.getValue();

                    // set the input element value to the escaped value of contents
                    document.getElementById('{0}').value = $('<div/>').text( contents  ).html().replace(/&#39/g,""&apos"");

                    {3}
                }});

                // disable warning about block scrolling
                ce_{0}.$blockScrolling = Infinity;

                ce_{0}.setReadOnly({4});

                ce_{0}.on('blur', function(e) {{
                    {5}
                }});

                // make sure the editor is sized correctly (fixes an issue when editor is used in a modal)
                setTimeout(function () {{
                    ce_{0}.resize();
                }}, 0);

                {6}
";

            string script = string.Format(
                scriptFormat,
                this.ClientID,                         // {0}
                EditorThemeAsString(this.EditorTheme), // {1}
                EditorModeAsString(this.EditorMode),   // {2}
                this.OnChangeScript,                   // {3}
                this.ReadOnly.ToTrueFalse().ToLower(), // {4}
                this.OnBlurScript,                     // {5}
                this.OnLoadCompleteScript,             // {6}
                this.LineWrap.ToString().ToLower()     // {7}
                );

            ScriptManager.RegisterStartupScript(this, this.GetType(), "codeeditor_" + this.ClientID, script, true);

            base.RenderControl(writer);
        }
示例#4
0
        /// <summary>
        /// Renders the base control.
        /// </summary>
        /// <param name="writer">The writer.</param>
        public void RenderBaseControl(HtmlTextWriter writer)
        {
            // NOTE: Some of the plugins in the Full (72 plugin) build of CKEditor are buggy, so we are just using the Standard edition.
            // This is why some of the items don't appear in the RockCustomConfiguFull toolbar (like the Justify commands)
            string ckeditorInitScriptFormat = @"
// ensure that ckEditor.js link is added to page
if (!$('#ckeditorJsLib').length) {{
    // by default, jquery adds a cache-busting parameter on dynamically added script tags. set the ajaxSetup cache:true to prevent this
    $.ajaxSetup({{ cache: true }});
    $('head').prepend(""<script id='ckeditorJsLib' src='{12}' />"");
}}

// allow i tags to be empty (for font awesome)
CKEDITOR.dtd.$removeEmpty['i'] = false

// In IE, the CKEditor doesn't accept keyboard input when loading again within the same page instance.  Destroy fixes it, but destroy throws an exception in Chrome
if (CKEDITOR.instances.{0}) {{
    try
    {{
        CKEDITOR.instances.{0}.destroy();
    }}
    catch (ex)
    {{
        // ignore error
    }}
}}
  
CKEDITOR.replace('{0}', {{ 
    {11}
    allowedContent: true,
    toolbar: Rock.htmlEditor.toolbar_RockCustomConfig{1},
    removeButtons: '',
    baseFloatZIndex: 200000,  // set zindex to be 200000 so it will be on top of our modals (100000)
    entities: false, // stop CKEditor from using HTML entities in the editor output. Prevents single quote from getting escaped, etc
    htmlEncodeOutput: true,
    extraPlugins: '{5}',
    resize_maxWidth: '{3}',
    rockFileBrowserOptions: {{ 
    documentFolderRoot: '{6}', 
    imageFolderRoot: '{7}',
    imageFileTypeWhiteList: '{8}',
    fileTypeBlackList: '{9}'
    }},
    rockMergeFieldOptions: {{ mergeFields: '{10}' }},
    rockTheme: '{13}',
    on : {{
        change: function (e) {{
            // update the underlying TextElement on every little change (when in WYSIWIG mode) to ensure that Posting and Validation works consistently (doing it OnSubmit or OnBlur misses some cases)
            e.editor.updateElement();  
            {4}
        }},
        instanceReady: function (e) {{

            CKEDITOR.instances.{0}.updateElement();

            // update the underlying TextElement when there is a change event in SOURCE mode
            $('#cke_{0}').on( 'change paste', '.cke_source', function(e, data) {{
                CKEDITOR.instances.{0}.updateElement();
            }});

            // In IE, clicking the Source button does not cause the .cke_source to lose focus 
            // and fire the onchange event, so also updateElement when source button is clicked
            $('#cke_{0} .cke_button__source').click( function(e, data) {{
                CKEDITOR.instances.{0}.updateElement();
            }});

            // set the height
            if ('{2}' != '') {{
              var topHeight = $('#' + e.editor.id + '_top').height();
              var contentHeight = '{2}'.replace('px','') - topHeight - 40;
              $('#' + e.editor.id + '_contents').css('height', contentHeight);
            }}
        }}
    }}
}}
);
            ";

            string customOnChangeScript = null;

            if (!string.IsNullOrWhiteSpace(this.OnChangeScript))
            {
                customOnChangeScript = @"
                // custom on change script 
                " + this.OnChangeScript;
            }

            List <string> enabledPlugins = new List <string>();

            if (MergeFields.Any())
            {
                enabledPlugins.Add("rockmergefield");
            }

            // only show the File/Image plugin if they have Auth to the file browser page
            var fileBrowserPage = new Rock.Model.PageService(new RockContext()).Get(Rock.SystemGuid.Page.CKEDITOR_ROCKFILEBROWSER_PLUGIN_FRAME.AsGuid());

            if (fileBrowserPage != null)
            {
                var currentPerson = this.RockBlock().CurrentPerson;
                if (currentPerson != null)
                {
                    if (fileBrowserPage.IsAuthorized(Authorization.VIEW, currentPerson))
                    {
                        enabledPlugins.Add("rockfilebrowser");
                    }
                }
            }

            var globalAttributesCache = GlobalAttributesCache.Read();

            string imageFileTypeWhiteList = globalAttributesCache.GetValue("ContentImageFiletypeWhitelist");
            string fileTypeBlackList      = globalAttributesCache.GetValue("ContentFiletypeBlacklist");

            string documentFolderRoot = this.DocumentFolderRoot;
            string imageFolderRoot    = this.ImageFolderRoot;

            if (this.UserSpecificRoot)
            {
                var currentUser = this.RockBlock().CurrentUser;
                if (currentUser != null)
                {
                    documentFolderRoot = System.Web.VirtualPathUtility.Combine(documentFolderRoot.EnsureTrailingBackslash(), currentUser.UserName.ToString());
                    imageFolderRoot    = System.Web.VirtualPathUtility.Combine(imageFolderRoot.EnsureTrailingBackslash(), currentUser.UserName.ToString());
                }
            }

            // Make sure that if additional configurations are defined, that the string ends in a comma.
            if (!string.IsNullOrWhiteSpace(this.AdditionalConfigurations) && !this.AdditionalConfigurations.Trim().EndsWith(","))
            {
                this.AdditionalConfigurations = this.AdditionalConfigurations.Trim() + ",";
            }

            string ckEditorLib = ((RockPage)this.Page).ResolveRockUrl("~/Scripts/ckeditor/ckeditor.js", true);

            string ckeditorInitScript = string.Format(ckeditorInitScriptFormat,
                                                      this.ClientID,                                              // {0}
                                                      this.Toolbar.ConvertToString(),                             // {1}
                                                      this.Height,                                                // {2}
                                                      this.ResizeMaxWidth ?? 0,                                   // {3}
                                                      customOnChangeScript,                                       // {4}
                                                      enabledPlugins.AsDelimited(","),                            // {5}
                                                      Rock.Security.Encryption.EncryptString(documentFolderRoot), // {6} encrypt the folders so the folder can only be configured on the server
                                                      Rock.Security.Encryption.EncryptString(imageFolderRoot),    // {7}
                                                      imageFileTypeWhiteList,                                     // {8}
                                                      fileTypeBlackList,                                          // {9}
                                                      this.MergeFields.AsDelimited(","),                          // {10}
                                                      this.AdditionalConfigurations,                              // {11}
                                                      ckEditorLib,                                                // {12}
                                                      ((RockPage)this.Page).Site.Theme                            // {13}
                                                      );

            ScriptManager.RegisterStartupScript(this, this.GetType(), "ckeditor_init_script_" + this.ClientID, ckeditorInitScript, true);

            base.RenderControl(writer);
        }
示例#5
0
        /// <summary>
        /// Renders the base control.
        /// </summary>
        /// <param name="writer">The writer.</param>
        public void RenderBaseControl(HtmlTextWriter writer)
        {
            string summernoteInitScriptFormat = @"
$(document).ready( function() {{
    var summerNoteEditor_{0} = $('#{0}').summernote({{
        height: '{2}', //set editable area's height
        toolbar: Rock.htmlEditor.toolbar_RockCustomConfig{11},

        popover: {{
          image: [
            ['imagesize', ['imageSize100', 'imageSize50', 'imageSize25']],
            ['custom', ['rockimagebrowser']],
            ['float', ['floatLeft', 'floatRight', 'floatNone']],
            ['remove', ['removeMedia']]
          ],
          link: [
            ['link', ['linkDialogShow', 'unlink']]
          ],
          air: [
            ['color', ['color']],
            ['font', ['bold', 'underline', 'clear']],
            ['para', ['ul', 'paragraph']],
            ['table', ['table']],
            ['insert', ['link', 'picture']]
          ]
        }},

        callbacks: {{
           {12} 
        }},

        buttons: {{
            rockfilebrowser: RockFileBrowser,
            rockimagebrowser: RockImageBrowser, 
            rockmergefield: RockMergeField,
            rockcodeeditor: RockCodeEditor,
            rockpastetext: RockPasteText,
            rockpastefromword: RockPasteFromWord
        }},

        rockFileBrowserOptions: {{ 
            enabled: {3},
            documentFolderRoot: '{4}', 
            imageFolderRoot: '{5}',
            imageFileTypeWhiteList: '{6}',
            fileTypeBlackList: '{7}'
        }},

        rockMergeFieldOptions: {{ 
            enabled: {9},
            mergeFields: '{8}' 
        }},
        rockTheme: '{10}',

        codeEditorOptions: {{
            controlId: '{13}',
            inCodeEditorModeHiddenFieldId: '{14}'
        }},

        // summernote-cleaner.js plugin options
        cleaner:{{
                el:'#{0}',  // Element ID or Class used to Initialise Summernote.
                notTime:2400, // Time to display Notifications.
                action:'paste', // both|button|paste 'button' only cleans via toolbar button, 'paste' only clean when pasting content, both does both options.
        }}

    }});

    if ({15} && RockCodeEditor) {{
        RockCodeEditor(summerNoteEditor_{0}.data('summernote'), true).click();
    }}

}});
";

            bool rockMergeFieldEnabled  = MergeFields.Any();
            bool rockFileBrowserEnabled = false;

            // only show the File/Image plugin if they have Auth to the file browser page
            var fileBrowserPage = new Rock.Model.PageService(new RockContext()).Get(Rock.SystemGuid.Page.HTMLEDITOR_ROCKFILEBROWSER_PLUGIN_FRAME.AsGuid());

            if (fileBrowserPage != null)
            {
                var currentPerson = this.RockBlock().CurrentPerson;
                if (currentPerson != null)
                {
                    if (fileBrowserPage.IsAuthorized(Authorization.VIEW, currentPerson))
                    {
                        rockFileBrowserEnabled = true;
                    }
                }
            }

            var globalAttributesCache = GlobalAttributesCache.Read();

            string imageFileTypeWhiteList = globalAttributesCache.GetValue("ContentImageFiletypeWhitelist");
            string fileTypeBlackList      = globalAttributesCache.GetValue("ContentFiletypeBlacklist");

            string documentFolderRoot = this.DocumentFolderRoot;
            string imageFolderRoot    = this.ImageFolderRoot;

            if (this.UserSpecificRoot)
            {
                var currentUser = this.RockBlock().CurrentUser;
                if (currentUser != null)
                {
                    documentFolderRoot = System.Web.VirtualPathUtility.Combine(documentFolderRoot.EnsureTrailingBackslash(), currentUser.UserName.ToString());
                    imageFolderRoot    = System.Web.VirtualPathUtility.Combine(imageFolderRoot.EnsureTrailingBackslash(), currentUser.UserName.ToString());
                }
            }

            string callbacksOption = null;

            if (!string.IsNullOrEmpty(this.OnChangeScript))
            {
                callbacksOption = string.Format(
                    @" onKeyup: function() {{  
    {0}  
}}",
                    this.OnChangeScript);
            }

            string summernoteInitScript = string.Format(
                summernoteInitScriptFormat,
                this.ClientID,                                              // {0}
                null,                                                       // {1}
                this.Height,                                                // {2}
                rockFileBrowserEnabled.ToTrueFalse().ToLower(),             // {3}
                Rock.Security.Encryption.EncryptString(documentFolderRoot), // {4} encrypt the folders so the folder can only be configured on the server
                Rock.Security.Encryption.EncryptString(imageFolderRoot),    // {5}
                imageFileTypeWhiteList,                                     // {6}
                fileTypeBlackList,                                          // {7}
                this.MergeFields.AsDelimited(","),                          // {8}
                rockMergeFieldEnabled.ToTrueFalse().ToLower(),              // {9}
                ((RockPage)this.Page).Site.Theme,                           // {10}
                this.Toolbar.ConvertToString(),                             // {11}
                callbacksOption,                                            // {12}
                _ceEditor.ClientID,                                         // {13}
                _hfInCodeEditorMode.ClientID,                               // {14}
                StartInCodeEditorMode.ToTrueFalse().ToLower()               // {15}
                );

            ScriptManager.RegisterStartupScript(this, this.GetType(), "summernote_init_script_" + this.ClientID, summernoteInitScript, true);

            // add script on demand only when there will be an htmleditor rendered
            if (ScriptManager.GetCurrent(this.Page).IsInAsyncPostBack)
            {
                ScriptManager.RegisterClientScriptInclude(this.Page, this.Page.GetType(), "summernote-lib", ((RockPage)this.Page).ResolveRockUrl("~/Scripts/summernote/summernote.min.js", true));
                var bundleUrl = System.Web.Optimization.BundleResolver.Current.GetBundleUrl("~/Scripts/Bundles/RockHtmlEditorPlugins");
                ScriptManager.RegisterClientScriptInclude(this.Page, this.Page.GetType(), "summernote-plugins", bundleUrl);
            }

            // set this textbox hidden until we can run the js to attach summernote to it
            this.Style[HtmlTextWriterStyle.Display] = "none";

            base.RenderControl(writer);
        }