public static void InsertEditorHtmlIntoElement(IContentSourceSidebarContext contentSourceContext, SmartContentSource source, ISmartContent sContent, IHTMLElement element) { string content = source.GenerateEditorHtml(sContent, contentSourceContext); // If the plugin returned null has the HTML it would like to insert, remove the element from the editor if (content == null) { HTMLElementHelper.RemoveElement(element); } else { InsertContentIntoElement(content, sContent, contentSourceContext, element); } }
private static void ProcessInitializedImages(List <NewImageInfo> newImages, IBlogPostHtmlEditor currentEditor, ContentEditor editor, Control owner, bool selectLastImage) { // Remove all invalid images first List <NewImageInfo> newImagesToUpdate = new List <NewImageInfo>(); for (int i = 0; i < newImages.Count; i++) { NewImageInfo info = newImages[i]; if (info.Remove) { using (ContentEditor.EditorUndoUnit undo = new ContentEditor.EditorUndoUnit(currentEditor, true)) { info.DisabledImageBehavior.DetachFromElement(); HTMLElementHelper.RemoveElement(info.Element); undo.Commit(); } } else { newImagesToUpdate.Add(info); } } // Queue up processing for any remaining valid images MultiTaskHelper tasks = new MultiTaskHelper(30); for (int i = 0; i < newImagesToUpdate.Count; i++) { bool lastElement = i == (newImagesToUpdate.Count - 1); NewImageInfo info = newImagesToUpdate[i]; tasks.AddWork(delegate { // WinLive 214012: If the original insertion operation is undone before we get to this point make // sure we don't attempt to update the HTML. Elements that are removed via an undo, but that we // still hold a reference to, are put into another document whose readyState is "uninitialized". // It's also possible that the picture has already been updated if a user undoes and redoes the // initial insertion multiple times. IHTMLDocument2 doc = (IHTMLDocument2)info.Element.document; if (doc == null || doc.readyState.Equals("uninitialized", StringComparison.OrdinalIgnoreCase) || BlogPostImageDataList.LookupImageDataByInlineUri(editor.ImageList, info.ImageData.InlineImageFile.Uri) != null) { info.DisabledImageBehavior.DetachFromElement(); return; } using (new QuickTimer("ProcessInitializedImage")) using (ContentEditor.EditorUndoUnit undo = new ContentEditor.EditorUndoUnit(currentEditor, true)) { editor.ImageList.AddImage(info.ImageData); info.Element.setAttribute("src", UrlHelper.SafeToAbsoluteUri(info.ImageData.InlineImageFile.Uri), 0); info.Element.removeAttribute("srcDelay", 0); // Create the decorators ImageEditingPropertyHandler.UpdateImageSource(info.ImageInfo, info.Element, editor, new ImageInsertHandler(), ImageDecoratorInvocationSource.InitialInsert); // Manually detach the behavior so that the image can be selected and resized. info.DisabledImageBehavior.DetachFromElement(); if (lastElement) { ApplicationPerformance.EndEvent("InsertImage"); HandleNewImage((BlogPostHtmlEditorControl)currentEditor, owner, info.Element, selectLastImage); } undo.Commit(); if (editor.ETWProvider != null) { editor.ETWProvider.WriteEvent("InlinePhotoEnd"); } } }); } // If there were no images to update, stop the perf timer if (newImagesToUpdate.Count == 0) { ApplicationPerformance.EndEvent("InsertImage"); } // When the editor is closing, or changing to a new blog post we need to get rid of this object // which will then stop all the unfinished images from continuing to load. editor.DisposeOnEditorChange(tasks); tasks.Start(); }
/// <summary> /// Takes the source HTML and makes necessary modifications to keep the source formatting as if it were to be /// pasted into the destination range. /// </summary> /// <param name="sourceRange">The range containing the HTML that is being copied.</param> /// <param name="destinationRange">The range that the source HTML will be copied to.</param> /// <returns>A serialized string of the source HTML with necessary modifications to keep the source formatting /// or null if unsuccessful.</returns> private string KeepSourceFormatting(MarkupRange sourceRange, MarkupRange destinationRange) { Debug.Assert(sourceRange.Start.Container.GetOwningDoc() == destinationRange.Start.Container.GetOwningDoc(), "Ranges must share an owning document!"); // We will temporarily add comments to the destination document to mark the destinationRange. IHTMLElement startComment = null; IHTMLElement endComment = null; try { // This is our true destination document. IHTMLDocument2 destinationDocument = destinationRange.Start.Container.Document; MshtmlMarkupServices destinationMarkupServices = new MshtmlMarkupServices((IMarkupServicesRaw)destinationDocument); // However, we'll use a temp destination because we don't want to paste anything into the real // document yet as it could fail, it would fire events, images would start loading, etc. MarkupContainer temporaryDestinationContainer = destinationMarkupServices.CreateMarkupContainer(); MarkupPointer temporaryDestinationPointer = destinationMarkupServices.CreateMarkupPointer(); temporaryDestinationPointer.MoveToContainer(temporaryDestinationContainer, true); // We add in comments to the destination document so that when we copy this range over to the fake // destination we'll be able to find the range again. destinationRange.Start.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Left; destinationRange.End.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Right; string startMarker = string.Format(CultureInfo.InvariantCulture, "<!--{0}-->", Guid.NewGuid()); destinationMarkupServices.InsertHtml(startMarker, destinationRange.Start); startComment = destinationRange.Start.Right(false).Element; string endMarker = string.Format(CultureInfo.InvariantCulture, "<!--{0}-->", Guid.NewGuid()); destinationMarkupServices.InsertHtml(endMarker, destinationRange.End); endComment = destinationRange.End.Left(false).Element; try { // Copy over the entire destination document into the fake destination document. MarkupRange destinationAll = SelectAll(destinationDocument); destinationMarkupServices.Copy(destinationAll.Start, destinationAll.End, temporaryDestinationPointer); // Find the original destination range in this copy. MarkupRange temporaryDestinationRange = FindMarkedFragment(temporaryDestinationContainer.Document, startMarker, endMarker); if (temporaryDestinationRange != null) { // Do the work to keep the source formatting. MarkupRange inlinedRange = new KeepSourceFormatting(sourceRange, temporaryDestinationRange).Execute(); if (inlinedRange != null) { return(inlinedRange.HtmlText); } } } finally { // WinLive 249077: Clear the temporary destination container, otherwise behaviors may // inadvertently attach to elements in the MarkupContainer. temporaryDestinationContainer.Document.body.innerHTML = String.Empty; } } catch (Exception e) { // I really dont want some funky html on the clipboard that causes a problem with this code // to prevent a paste from going through. Trace.Fail("Failed to get inline css for selection: " + e); } finally { Debug.Assert(startComment is IHTMLCommentElement, "Didn't find start comment or it wasn't created."); if (startComment is IHTMLCommentElement) { HTMLElementHelper.RemoveElement(startComment); } Debug.Assert(endComment is IHTMLCommentElement, "Didn't find end comment or it wasn't created."); if (endComment is IHTMLCommentElement) { HTMLElementHelper.RemoveElement(endComment); } } return(null); }