I'm learning Watin and I came across an interesting piece of html code:
<label class="age_label years_old" for="total_age">
<b>34</b>
<span class="placeholder">How old are you?</span>
<span class="years_old">years old</span>
<span class="years_young">years young</span>
</label>
How do I get to 34?, Im completely lost as I'm used to selecting inputs by Id or Class. But here its not an input. Its just a html tag.
I want to SET/*REPLACE* 34 with another number using watin, but how?
WatiN doesn't have setters for tag values like what you're asking. It can easily be done through javascript though. And combining a JS call with the WatiN .GetJavascriptElementReference to get the JS element makes what you're trying to do very simple. (I'm sure there is a pure JS way to do this, but I'm better in WatiN than JS these days) As is hopefully obvious, finding the first bold tag is a very, very fragile approach and if a better approach could be taken for element location.
And, if you're using this "setter" action for testing - it is a nasty smell because you're changing something a user wouldn't be able to do.
Example code
var jsRef = myIE.ElementsWithTag("b")[0].GetJavascriptElementReference();
myIE.Eval(string.Format("{0}.innerHTML = 'fred'", jsRef));
Above tested with OP's HTML, Watin 2.1, IE9, Win7-64 => works as expected.
I'd imagine something like
var result = browserInstance.LabelField(lf => lf.GetAttributeValue("class").Contains("age_label years_old")).Children().First().Text;
If this is your only <b> tag on the page, then this might work:
IE.ElementWithTag("b", Find.First());
Good luck.
Related
I have a controller which generates a string containing html markup. When it displays on views, it is displayed as a simple string containing all tags.
I tried to use an Html helper to encode/decode to display it properly, but it is not working.
string str= "seeker has applied to Job floated by you.</br>";
On my views,
#Html.Encode(str)
You are close you want to use #Html.Raw(str)
#Html.Encode takes strings and ensures that all the special characters are handled properly. These include characters like spaces.
You should be using IHtmlString instead:
IHtmlString str = new HtmlString("seeker has applied to Job floated by you.</br>");
Whenever you have model properties or variables that need to hold HTML, I feel this is generally a better practice. First of all, it is a bit cleaner. For example:
#Html.Raw(str)
Compared to:
#str
Also, I also think it's a bit safer vs. using #Html.Raw(), as the concern of whether your data is HTML is kept in your controller. In an environment where you have front-end vs. back-end developers, your back-end developers may be more in tune with what data can hold HTML values, thus keeping this concern in the back-end (controller).
I generally try to avoid using Html.Raw() whenever possible.
One other thing worth noting, is I'm not sure where you're assigning str, but a few things that concern me with how you may be implementing this.
First, this should be done in a controller, regardless of your solution (IHtmlString or Html.Raw). You should avoid any logic like this in your view, as it doesn't really belong there.
Additionally, you should be using your ViewModel for getting values to your view (and again, ideally using IHtmlString as the property type). Seeing something like #Html.Encode(str) is a little concerning, unless you were doing this just to simplify your example.
you can use
#Html.Raw(str)
See MSDN for more
Returns markup that is not HTML encoded.
This method wraps HTML markup using the IHtmlString class, which
renders unencoded HTML.
I had a similar problem with HTML input fields in MVC. The web paged only showed the first keyword of the field.
Example: input field: "The quick brown fox" Displayed value: "The"
The resolution was to put the variable in quotes in the value statement as follows:
<input class="ParmInput" type="text" id="respondingRangerUnit" name="respondingRangerUnit"
onchange="validateInteger(this.value)" value="#ViewBag.respondingRangerUnit">
I had a similar problem recently, and google landed me here, so I put this answer here in case others land here as well, for completeness.
I noticed that when I had badly formatted html, I was actually having all my html tags stripped out, with just the non-tag content remaining. I particularly had a table with a missing opening table tag, and then all my html tags from the entire string where ripped out completely.
So, if the above doesn't work, and you're still scratching your head, then also check you html for being valid.
I notice even after I got it working, MVC was adding tbody tags where I had none. This tells me there is clean up happening (MVC 5), and that when it can't happen, it strips out all/some tags.
I need to retrieve some info from an html doc since the web service to get a json or an xml is still not ready. Im working with c# and using regular expressions to get the data i need from the html string. I've managed to get the div i want to work with from the whole html string but now i'm having trouble getting the info between the first span tag.
I've attempted to retrieve the data between ; and the first closing span tag but what i really want is the content between the first span tag.
Here's the regular expression i've written so far, but it's not working:
".*;(?<Content>(\r|\n|.)*)</span>"
I also tried this but didnt work either:
"<span class=""type"">(?<Content>(\r|\n|.)*)</span>"
Here is the div i want to retrieve the data from:
<div class="main">ABASASDFÓ 18/06/2014 17:38h Blabla Balbal <span class="type">15.80€ </span>+1.94 % +0.30€ | HOME <SPAN class="type2">11,398.70</span> +0.65 % +74.10</div>
EDIT: I can't use Htmlagilitypack since my client does not want us to use any external library. I've also heard about using the XmlReader but i'm not sure the structure of the html will match an xml one accordingly.
This regex will capture the string:
"<span class=\"type\">(?<Content>([^<]*))</span>"
Although, I agree with other answers, you should use something like Path instead of Regexes for parsing html.
Here's how it is done with a regex in Javascript. You should be able to adapt this for C# pretty easily.
var inner = html.match( /<span class="type"(?:\s+[a-z]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)))*\s*>([\S\s]*)<\/span>/i)[1];
Fiddle: http://jsfiddle.net/GarryPas/uk32r8vz/
You want to use XPath for that. Something like this:
div/span/text()
I understand not wanting some external 3rd party library in your solution, the solution to that is to go fetch the source code of the entire library:
https://htmlagilitypack.codeplex.com/
Now you don't have an external library, you have an internal library and you can use the right tool for the job!
XmlReader is a fairly low-level tool, it could technically do the job for you but what you're more after is "use XmlReader to do XPath" which is talked about here: https://msdn.microsoft.com/en-us/library/ms950778.aspx
The XPathReader class is the result of all that, which has been superseded by LINQ to XML: https://msdn.microsoft.com/en-ca/library/bb387098.aspx
So another option here is to try to use some LINQ to process your HTML file, but that might be tricky since HTML isn't good XML. Still, it's another option if you're looking for those.
I'm having a bit of a hard time trying to format my HTML when using HtmlTextWriter. It seems that some tags will automatically go to a new line and some won't.
Is there a way to stop this from happening so all tags are created equally and leave the formatting completely up to me?
In my particular case I'm building out a <ul>'s and <li>'s for a custom HTML Sitemap.
The immediate tag that comes after an <ul> will wrap to a new line.
This is not the case for a <li> tag.
If anyone needs clarification please ask question.
Are you using RenderBeginTag? That method will handle some things automatically, and among other things, it will put line breaks (and indentation) in elements that aren't inline (e.g. ul versus span).
If you want to do the rendering manually, use WriteBeginTag("ul") or WriteFullBeginTag("ul") instead.
Note that WriteBeginTag will still handle indentation. However, you have full control over that if you only use the WriteXXX methods.
In the end, though, do those endlines really bother you at all? You do use compression, right? The overhead usually isn't very significant...
I am trying to add dynamic id to div inside a foreach loop concatenated with value of variable i. It throws syntax errors. What might be the issue. Can we achieve this solution without using a for loop ?
#{int i=1;}
#foreach (var or in Model.Names)
{
<div oid="#or.Id" mode="0" oids="#or.Id" id="tr"+i>
#or.Name
</div>
i++;
}
You want to construct ID in C# segment of code. One option is to do whole construction with string format:
<div oid="#or.Id" mode="0" oids="#or.Id" id="#string.Format("tr{0}",i)">
Or id="#("tr"+i)" or id="tr#(i)"
Note that you can't do just id="tr#i" because the Razor syntax parser ignores "text#text" as it looks like a normal email address.
You can't append like this:
id="tr"+i>
It must be:
id="tr#i">
You need the #.. since it won't be able to deduce between markup and Razor at that point.
in the newly C# 6 you can directly use id="#($"tr{i}")"
for myself, none of this solutions worked but adding my #i first did work, id="#i+AnyText"
after building it, and inspecting ill get id="1+AnyText", for the
next one id="2+AnyText" and so on (im using 2013vs)..
hope that helps anyone, have a nice day.
After struggling with this for a while I found that id="#("tr"+i)" did the job for me
Why doesn't this work?
<input type="button" id="btnAccept" value="Accept" onclick='<%# String.Format("accept('{0}','{1}','{2}','{3}-{4}');", Container.DataItem("PositionID"), Container.DataItem("ApplicantID"), Container.DataItem("FullName"), Container.DataItem("DepartmentName"), Container.DataItem("PositionTitle"))%>' />
The onclick doesn't do anything.
Your best bet is to look at the generated HTML. I think it's a really good habit to check the generated HTML in text format and how it renders on-screen, all the time. Besides errors such as this (which can easily be spotted in the generated HTML), it will help you catch other possible invalid uses of HTML which may render as intended in one browser while rendering terribly in another. HTML rendering engines employ many tricks to try and make invalid HTML look okay.
Anyway, all things aside (such as, assuming accept(...) exists, and all other calls in the tag are correct) I think the issue you are having is as follows:
onclick='<%# String.Format("accept('{0}','{1}','{2}','{3}-{4}');", ... )%>'
This line is probably going to evaluate to look something like this:
onclick='accept('{0}','{1}','{2}','{3}-{4}');'
With all single quotes, all the onclick attribute will see is onclick='accept(' which is not a valid javascript method call. You're going to want to use the "" strings, which you can embed in the format string by escaping them.
String.Format("accept(\"{0}\",\"{1}\",\"{2}\",\"{3}-{4}\");", ... )
Then, you should be able to get the correct combination of ' and " within the attribute:
onclick='accept("{0}","{1}","{2}","{3}-{4}");'