Ghost cell in IE9 with Repeater Control - c#

IE9 Generate blank cell or you can say Ghost Cell, with ASP.Net Repeater control.
I try javascript regural expression. Render function to run reg. exp. but the page holds few update controls and generate error.
Error: sys.webforms.pagerequestmanagerservererrorexception the message
received from the server could not be parsed. ScriptResource.axd
I try all the well known links for this error.
Please suggest me if you really have...
Thank You
protected override void Render(HtmlTextWriter writer)
{
using (HtmlTextWriter htmlwriter = new HtmlTextWriter(new System.IO.StringWriter()))
{
base.Render(htmlwriter);
string html = htmlwriter.InnerWriter.ToString();
if ((ConfigurationManager.AppSettings.Get("RemoveWhitespace") + string.Empty).Equals("true", StringComparison.OrdinalIgnoreCase))
{
//html = Regex.Replace(html, #"(?<=[^])\t{2,}|(?<=[>])\s{2,}(?=[<])|(?<=[>])\s{2,11}(?=[<])|(?=[\n])\s{2,}", string.Empty);
html = Regex.Replace(html, #"(?<=<td[^>]*>)(?>\s+)(?!<table)|(?<!</table>\s*)\s+(?=</td>)", string.Empty);
html = html.Replace(";\n", ";");
}
writer.Write(html.Trim());
}
another Solution is, but fail for Repeater
var expr = new RegExp('>[ \t\r\n\v\f]*<', 'g');
document.body.innerHTML = document.body.innerHTML.replace(expr, '><');

You can access the Repeater control directly (before it's written to the page and rendered by IE) and remove the cells based on their index.

Need to remove spaces between "< /td >" and "< td >".

Found a very useful script to prevent unwanted cells in your html table while rendering in IE9 browser.
function removeWhiteSpaces()
{
$('#myTable').html(function(i, el) {
return el.replace(/>\s*</g, '><');
});
}
This javascript function you should call when the page loads (i.e. onload event)

Related

How to get input element from Literal

On the sever side, I've created, a literal with text set to an input type file element with runat = 'server' property, mode set to passThrough and append it to a div. Both the literal and input element have it's own unique id. My issue is trying to get that input element from the div tag. I'm able to get the literal programmatically, but the literal doesn't contain any controls and text value has the input element I need. I tried looking for the input element o it's own and keep getting null. I've inspected the page and I see the input element with runat='server'and it's and yet I can't get it. I need to be able to get this input element in order to upload it's file.
This is what I've tried so far:
Client-Side:
<div runat="server" id="docRequeridosMainDiv" style="display: table;
width: 60%; text-align: right">
<%-- Control set on server side --%>
</div>
Server-Side: (Testing this on pageload event)
//Attach inivisible input type file
uploadLit.Text += string.Format(#"<div><input type='file' id='{0}File' runat = 'server' style='display: none;'
onchange='" + docsRequeridos.ElementAt(i).Nombre + #"FileSelected()' /></div>", lbl.Text);
uploadLit.ID = lbl.Text + "FileLit";
docRequeridosMainDiv.Controls.Add(uploadLit);
//var lit = (Literal)docRequeridosMainDiv.FindControl(uploadLit.ID);
var lit = (HtmlGenericControl)docRequeridosMainDiv.FindControl(lbl.Text +"File");
Ignore the event attached to input, that works.
I've debugged the commented lit and on the controls collection has 0 but the text has the input. The second lit is returns a null value.
Tried getting it with the same Findcontrol line on a click event and still same result. Literal with no controls.
Just in case you're wondering why the input is display:none cause I'm doing a custom file upload, but that's not important cause every other functionality works, the only on that doesn't work is this one.
FindControl() will find only server controls. Adding html control (with runat="server" as string) into a Literal will not make those controls servier-side. But you can use HtmlInputFile to achieve the same, like this:
var fileInput = new HtmlFileInput
{
ID = lbl.Text + "File"
};
fileInput.Attributes["onchange"] = docsRequeridos.ElementAt(i).Nombre + "FileSelected()";
fileInput.Attributes["style"] = "display:none";
docRequeridosMainDiv.Controls.Add(fileInput);
Now, you can find this control like:
var foundFileInput = docRequeridosMainDiv.FindControl(lbl.Text +"File") as HtmlFileInput;
If you want to wrap this file input with div, you need to make another HtmlGenericControl and add that fileInput to that; like this:
var myDiv = new HtmlGenericControl("div")
{
ID = "FileUploadContainer"
};
myDiv.Controls.Add(fileInput);
docRequeridosMainDiv.Controls.Add(myDiv); // Add myDiv instead of fileInput
This will generate exactly the html you wanted, but just programmatically (not with Literal string), and controls are now server-side.

How to get all Display text from a webpage in C#

Hi I am working on data scraping application in C#.
Actually I want to get all the Display text but not the html tags.
Here's My code
HtmlWeb web = new HtmlWeb();
HtmlAgilityPack.HtmlDocument doc = web.
Load(#"http://dawateislami.net/books/bookslibrary.do#!section:bookDetail_521.tr");
string str = doc.DocumentNode.InnerText;
This inner html is returning some tags and scripts as well but I want to only get the Display text that's visible to user.
Please help me.
Thanks
[I believe this will solve ur problem][1]
Method 1 – In Memory Cut and Paste
Use WebBrowser control object to process the web page, and then copy the text from the control…
Use the following code to download the web page:
Collapse | Copy Code
//Create the WebBrowser control
WebBrowser wb = new WebBrowser();
//Add a new event to process document when download is completed
wb.DocumentCompleted +=
new WebBrowserDocumentCompletedEventHandler(DisplayText);
//Download the webpage
wb.Url = urlPath;
Use the following event code to process the downloaded web page text:
Collapse | Copy Code
private void DisplayText(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser wb = (WebBrowser)sender;
wb.Document.ExecCommand(“SelectAll”, false, null);
wb.Document.ExecCommand(“Copy”, false, null);
textResultsBox.Text = CleanText(Clipboard.GetText());
}
Method 2 – In Memory Selection Object
This is a second method of processing the downloaded web page text. It seems to take just a bit longer (very minimal difference). However, it avoids using the clipboard and the limitations associated with that.
Collapse | Copy Code
private void DisplayText(object sender, WebBrowserDocumentCompletedEventArgs e)
{ //Create the WebBrowser control and IHTMLDocument2
WebBrowser wb = (WebBrowser)sender;
IHTMLDocument2 htmlDocument =
wb.Document.DomDocument as IHTMLDocument2;
//Select all the text on the page and create a selection object
wb.Document.ExecCommand(“SelectAll”, false, null);
IHTMLSelectionObject currentSelection = htmlDocument.selection;
//Create a text range and send the range’s text to your text box
IHTMLTxtRange range = currentSelection.createRange() as IHTMLTxtRange
textResultsBox.Text = range.text;
}
Method 3 – The Elegant, Simple, Slower XmlDocument Approach
A good friend shared this example with me. I am a huge fan of simple, and this example wins the simplicity contest hands down. It was unfortunately very slow compared to the other two approaches.
The XmlDocument object will load / process HTML files with only 3 simple lines of code:
Collapse | Copy Code
XmlDocument document = new XmlDocument();
document.Load(“www.yourwebsite.com”);
string allText = document.InnerText;
There you have it! Three simple ways to scrape only displayed text from web pages with no external “packages” involved.
Packages
To remove javascript and css:
foreach(var script in doc.DocumentNode.Descendants("script").ToArray())
script.Remove();
foreach(var style in doc.DocumentNode.Descendants("style").ToArray())
style.Remove();
To remove comments (untested):
foreach(var comment in doc.DocumentNode.Descendants("//comment()").ToArray())
comment.Remove()
For removing all html tags from a string you can use:
String output = inputString.replaceAll("<[^>]*>", "");
For removing a specific tag:
String output = inputString.replaceAll("(?i)<td[^>]*>", "");
Hope it helps :)

How to check if ContentPlaceHolder is empty?

How to check if ContentPlaceHolder is absolutely empty?
In the ContentPlaceHolder have text only, without tags and controls.
Example Page.Master:
<asp:ContentPlaceHolder runat="server" ID="Content" />
Example Test.aspx:
<asp:Content runat="server" ContentPlaceHolderID="Content">
Custom text without controls. Content.Controls.Count is 0 and Content.HasControls is false.
</asp:Content>
What I need to do is that when the placeholder is empty put a default content is in another control.
Overwrite tried twice for the same placeholder but I get error when dynamic load.
You can implement a method that will render the content control into a string, then check the string to find wheahter it contains any non-white space chars:
private bool HasContent(Control ctrl)
{
var sb = new System.Text.StringBuilder();
using (var sw = new System.IO.StringWriter(sb))
{
using(var tw = new HtmlTextWriter(sw))
{
ctrl.RenderControl(tw);
}
}
var output = sb.ToString().Trim();
return !String.IsNullOrEmpty(output);
}
protected void Page_PreRender(object sender, EventArgs e)
{
var placeholder = Master.FindControl("FeaturedContent");
var hasContent = HasContent(placeholder);
}
You need to find the ContentPLaceHolder on the master page first. Then you can cast the first control(which always exists) to LiteralControl and use it's Text property.
So this works as expected from Page_Load of the content-page:
protected void Page_Load(object sender, EventArgs e)
{
var cph = Page.Master.FindControl("Content") as ContentPlaceHolder;
if (contentPlaceHolder != null)
{
string textualContent = ((LiteralControl) cph.Controls[0]).Text;
if (string.IsNullOrEmpty(textualContent))
{
// ...
}
}
}
This seems to have changed, because I am seeing in 4.5 that HasControls DOES return true when there is only literal text in the Content, even a single whitespace. I do something like this in my master page:
<asp:Panel id="SidebarPanel" CssClass="Sidebar" runat="server">
<asp:ContentPlaceHolder id="SidebarContent" runat="server" />
</asp:Panel>
Sub Page_Load(...)
SidebarPanel.Visible = SidebarContent.HasControls
End Sub
This renders the sidebar content, if there is any, inside a <div class="Sidebar"> -- and avoids creating an empty div on the page when there's no content.
I really didn't want to run all the code for a render or risk that maybe some controls might have states that change after being rendered. So I came up with another approach.
public static int ChildrenCount(ContentPlaceHolder placeholder)
{
int total = 0;
total += placeholder.Controls.OfType<Control>().Where(x =>
(!(x is ContentPlaceHolder) && !(x is LiteralControl)) ||
(x is LiteralControl && !string.IsNullOrWhiteSpace(((LiteralControl)x).Text))
).Count();
foreach (var child in placeholder.Controls.OfType<ContentPlaceHolder>())
total += ChildrenCount(child);
return total;
}
For me the text I'd place directly into a Content element would be returned by OfType as a LiteralControl with the appropriate contents. Not only this but my formatting ("\r\n\t") would also be returned the same way. I'd also get ContentPlaceholders for subsequent master pages as they passed the slot in my web pages to the next master page or actual page.
So the task now is to get a count of controls that excludes these ContentPlaceholders and also excludes LiteralControls which are whitespace. This is pretty easy using the is operator. We'll just make sure a given control is neither of those types and then count it, or if it is a Literal we check if the contents are all whitespace or not. The last step is to recursively add the results of the same operation for all child ContentPlaceholders so nested master pages work as expected.
And then finally:
if (ChildrenCount(MyContentPlaceholder) == 0)
MyContentPlaceholder.Controls.Add(new LiteralControl("My default content!"));
My 2 cents:
If it's a constant content you'll have to insert AND there will be no <Content> at all:
<asp:ContentPlaceHolder>
<!-- Anything here will be inserted if there's no Content -->
</asp:ContentPlaceHolder>

How to find the Controls in panel (which is added through literal)

Textbox1.text is user can enter html page name, so that its is appending to panel through literal.(loading html page to pannel).
string val = TextBox1.Text;
string location = Server.MapPath(".");
string path = location + "\\HTML\\" + val + ".html"; // HTML IS FOLDER NAME IN MY PROJECT
string readText = System.IO.File.ReadAllText(path);
Panel1.Controls.Clear();
Literal lit = new Literal();
lit.Text = readText;
Panel1.Controls.Add(lit);
Actually in Html page few controls which are in format of input (<input style="position: relative;" id="T0" onmouseup="mUp(this.id)" class="ui-draggable" onmousedown="mDown(this.id)" value="" type="text">)
I have to find those id's and text to save in database.
how to find the controls in panel now?
Give an ID to the control when you add it.
Literal lit = new Literal();
lit.Text = readText;
lit.ID = "myLiteral";
Panel1.Controls.Add(lit);
Then you can get it back as follows:
Literal lit = (Literal)Panel1.FincControl("myLiteral");
Remember that dynamically added controls must be created added again on every PostBack that follows as long as you want to have access to them.
Give your Literal an ID and then you can access it via FindControl...
Literal myLiteral = Panel1.FindControl("litId") as Literal;
if (myLiteral != null)
{
// ... do something
}
EDIT: (Missed the last part of your question)
You need to use ParseControl([string value]) on the HTML content which returns a control and then add that control (containing all child controls) to the Panel. Then you can use FindControl to locate child controls. For this method, the controls must be .NET controls (ie.
Since you did not give id to the control, u can find them by Panel1.Controls[index], since it is the first control added u can access at Panel1.Controls[0]

How to display the string html contents into webbrowser control?

I have a C# win app program. I save the text with html format in my database but I want to show it in a webbrowser to my user.How to display the string html contents into webbrowser control?
Try this:
webBrowser1.DocumentText =
"<html><body>Please enter your name:<br/>" +
"<input type='text' name='userName'/><br/>" +
"<a href='http://www.microsoft.com'>continue</a>" +
"</body></html>";
Instead of navigating to blank, you can do
webBrowser1.DocumentText="0";
webBrowser1.Document.OpenNew(true);
webBrowser1.Document.Write(theHTML);
webBrowser1.Refresh();
No need to wait for events or anything else. You can check the MSDN for OpenNew, while I have tested the initial DocumentText assignment in one of my projects and it works.
As commented by Thomas W. - I almost missed this comment but I had the same issues so it's worth rewriting as an answer I think.
The main issue being that after the first assignment of webBrowser1.DocumentText to some html, subsequent assignments had no effect.
The solution as linked by Thomas can be found in detail at http://weblogs.asp.net/gunnarpeipman/archive/2009/08/15/displaying-custom-html-in-webbrowser-control.aspx however I will summarize below in case this page becomes unavailable in the future.
In short, due to the way the webBrowser control works, you must navigate to a new page each time you wish to change the content. Therefore the author proposes a method to update the control as:
private void DisplayHtml(string html)
{
webBrowser1.Navigate("about:blank");
if (webBrowser1.Document != null)
{
webBrowser1.Document.Write(string.Empty);
}
webBrowser1.DocumentText = html;
}
I have however found that in my current application I get a CastException from the line if(webBrowser1.Document != null). I'm not sure why this is, but I've found that if I wrap the whole if block in a try catch the desired effect still works. See:
private void DisplayHtml(string html)
{
webBrowser1.Navigate("about:blank");
try
{
if (webBrowser1.Document != null)
{
webBrowser1.Document.Write(string.Empty);
}
}
catch (CastException e)
{ } // do nothing with this
webBrowser1.DocumentText = html;
}
So every time the function to DisplayHtml is executed I receive a CastException from the if statement, so the contents of the if statement are never reached. However if I comment out the if statement so as not to receive the CastException, then the browser control doesn't get updated. I suspect there is another side effect of the code behind the Document property which causes this effect despite the fact that it also throws an exception.
Anyway I hope this helps people.
For some reason the code supplied by m3z (with the DisplayHtml(string) method) is not working in my case (except first time). I'm always displaying html from string. Here is my version after the battle with the WebBrowser control:
webBrowser1.Navigate("about:blank");
while (webBrowser1.Document == null || webBrowser1.Document.Body == null)
Application.DoEvents();
webBrowser1.Document.OpenNew(true).Write(html);
Working every time for me. I hope it helps someone.
Simple solution, I've tested is
webBrowser1.Refresh();
var str = "<html><head></head><body>" + sender.ToString() + "</body></html>";
webBrowser1.DocumentText = str;
webBrowser.NavigateToString(yourString);
Here is a little code. It works (for me) at any subsequent html code change of the WebBrowser control. You may adapt it to your specific needs.
static public void SetWebBrowserHtml(WebBrowser Browser, string HtmlText)
{
if (Browser != null)
{
if (string.IsNullOrWhiteSpace(HtmlText))
{
// Putting a div inside body forces control to use div instead of P (paragraph)
// when the user presses the enter button
HtmlText =
#"<html>
<head>
<meta http-equiv=""Content-Type"" content=""text/html; charset=UTF-8"" />
</head>
<div></div>
<body>
</body>
</html>";
}
if (Browser.Document == null)
{
Browser.Navigate("about:blank");
//Wait for document to finish loading
while (Browser.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
System.Threading.Thread.Sleep(5);
}
}
// Write html code
dynamic Doc = Browser.Document.DomDocument;
Doc.open();
Doc.write(HtmlText);
Doc.close();
// Add scripts here
/*
dynamic Doc = Document.DomDocument;
dynamic Script = Doc.getElementById("MyScriptFunctions");
if (Script == null)
{
Script = Doc.createElement("script");
Script.id = "MyScriptFunctions";
Script.text = JavascriptFunctionsSourcecode;
Doc.appendChild(Script);
}
*/
// Enable contentEditable
/*
if (Browser.Document.Body != null)
{
if (Browser.Version.Major >= 9)
Browser.Document.Body.SetAttribute("contentEditable", "true");
}
*/
// Attach event handlers
// Browser.Document.AttachEventHandler("onkeyup", BrowserKeyUp);
// Browser.Document.AttachEventHandler("onkeypress", BrowserKeyPress);
// etc...
}
}
Old question, but here's my go-to for this operation.
If browser.Document IsNot Nothing Then
browser.Document.OpenNew(True)
browser.Document.Write(My.Resources.htmlTemplate)
Else
browser.DocumentText = My.Resources.htmlTemplate
End If
And be sure that any browser.Navigating event DOES NOT cancel "about:blank" URLs. Example event below for full control of WebBrowser navigating.
Private Sub browser_Navigating(sender As Object, e As WebBrowserNavigatingEventArgs) Handles browser.Navigating
Try
Me.Cursor = Cursors.WaitCursor
Select Case e.Url.Scheme
Case Constants.App_Url_Scheme
Dim query As Specialized.NameValueCollection = System.Web.HttpUtility.ParseQueryString(e.Url.Query)
Select Case e.Url.Host
Case Constants.Navigation.URLs.ToggleExpander.Host
Dim nodeID As String = query.Item(Constants.Navigation.URLs.ToggleExpander.Parameters.NodeID)
:
:
<other operations here>
:
:
End Select
Case Else
e.Cancel = (e.Url.ToString() <> "about:blank")
End Select
Catch ex As Exception
ExceptionBox.Show(ex, "Operation failed.")
Finally
Me.Cursor = Cursors.Default
End Try
End Sub
The DisplayHtml(string html) recommended by m3z worked for me.
In case it helps somebody, I would also like to mention that initially there were some spaces in my HTML that invalidated the HTML and so the text appeared as a string. The spaces were introduced (around the angular brackets) when I pasted the HTML into Visual Studio. So if your text is still appearing as text after you try the solutions mentioned in this post, then it may be worth checking that the HTML syntax is correct.

Categories

Resources