I am using HtmlAgilityPack in c#. I created a div element with some attribute like,
HtmlNode div = HtmlNode.CreateNode("<div></div>");
div.Attributes.Add("style","width:100px;height:100px;color:red;position:absolute;");
Now I want to know that is there any method in HtmlAgilityPack by with i can access the style Attributes individually, like we do in jQuery :
$("div").width(); or $("div").css("width");
You could try using CsQuery, which is in fact like jQuery:
CQ div = CQ.Create("<div></div>");
div.CssSet( new {
width="100px",
height="100px",
color="red",
position="absolute"
});
//.. or
div.Css("width","100px").Css( ... ) ...
string width = div.Css("width"); // width=="100px"
int widthInt = div.Css<int>("width"); // widthInt==100
It implements every DOM manipulation method of jQuery, so the API should be very familiar. It also provides an implemention that mostly mimics the browser DOM, e.g.
var nodeName = div[0].NodeName; // nodeName=="DIV";
div[0].AppendChild(div.Document.CeateElement("span")); // add a span child
There are a couple exceptions, CssSet is one of them, where the overloaded methods in javascript didn't work out in C# so a different method had to be used. (The other one is AttrSet when setting from an object). It's also got extensive unit test coverage, including much of the test suite from jQuery ported to C#, and selectors are much faster than HTML Agility Pack (not to mention a lot less confusing since they're just CSS) thanks to a subselect-capable index.
Related
Is there a way to expose Razor syntax and (custom) helpers to people , but say ... not allow them to create code blocks or , to only limit them in the usage of the helpers and to not give them the power to execute pure C# code in the views ?
Any ideas and pointers to similar solutions are welcome !
update:// I would like to give the users the power to write their own HTML and access only to a list of html helpers. Mostly the default ones and the ones i create.
For example i do not want them to be able to execute code within #{ //code } blocks and
Also no using and #model ( not sure about this one)
only have access to #Html.* #if else for foreach
or better yet , give them access only to specific namespaces (this just a thought tho)
update://
After some testing , i found out that RazorEngine does as close as to what i'm trying to do : run the views in isolated environment and add access to specific namespaces.
I would not recommend you doing that. There simply is not an easy and reliable way to give them this ability without compromising the security of your site. If you trust your users then you could do it. If you don't then a templating engine such as DotLiquid is something far more appropriate for this purpose.
There is a project called RazorEngine, built upon Microsoft's Razor, that allows you to parse that syntax without being in the context of returning an MVC view. Here's how it's used:
string template = "Hello #Model.Name! Welcome to Razor!";
string result = Razor.Parse(template, new { Name = "World" });
You can also specify a customized template base, which should allow you to define only the Html Helpers you want to expose to your users:
Razor.SetTemplateBase(typeof(HtmlTemplateBase<>));
string template =
#"<html>
<head>
<title>Hello #Model.Name</title>
</head>
<body>
Email: #Html.TextBoxFor(m => m.Email)
</body>
</html>";
var model = new PageModel { Name = "World", Email = "someone#somewhere.com" };
string result = Razor.Parse(template, model);
you may try to change razor view engine and related classes to check for disallowed situations.
When source is generated (view engine generates a source file to compile ), you have to check it manually (by parsing c# or vb.net code). It is possible, but not feasible (really).
Even if you have managed to parse and check code, you have to identify your code (which is allowed) and customer code (which has restrictions).
At the end you have to accept the fact you can not really disallow anything other than using another template engine.
because
Your customers will find a way to make their views look like yours.
You cannot limit most basic required features like var r = new Random();
You cannot estimate what most basic requirements are
you cannot say No to your customers when they need to use their custom libraries
By the way, you may try another thing. Write a virtual path provider, and convert customer templates written in AviatrixTemplate when requested by runtime. By using this route, you still use razor engine, loose only a slight time when converting (it is one time only). But your AviatrixTemplate won't be hilighted, and you still need to check for disallowed code.
PS: a basic loop may give your users more then you want. for example following code allows creation of a class and call it for one time. they may use fully qualified class name or may use Activator.CreateInstance.
#for (var r = new Random(); r != null; r = null)
{
#r.NextDouble()
}
just do not bother.
I have never done this before, but it sounds like you want to give users the ability to write code and have it compiled for use, yes?
If so, you may want to look into the CSharpCodeProvider class, the RazorTemplateEngine class and the System.CodeCom.Compiler namespace.
Have a look here for some information on those classes:
CSharpCodeProvider: http://support.microsoft.com/kb/304655
RazorTemplateEngine: http://msdn.microsoft.com/en-us/library/system.web.razor.razortemplateengine(v=vs.111).aspx
How can I test css properties of any web-page element, which is defined in external css file. If I had, for example:
<div id="some-div" style="opasity: 10;"></div>
I could just take the value of style attribute, BUT I have all css properties defined in external ccs files. How can I test such elements and their properties?
Use IWebElement.GetCssValue
There is a method for getting the computed css style. I believe in c# it is the IWebElement.GetCssValue method.
Note that in the documentation for this method in ruby and java says the following. I assume it applies to c# even though it is not mentioned.
Note that shorthand CSS properties (e.g. background, font, border,
border-top, margin, margin-top, padding, padding-top, list-style,
outline, pause, cue) are not returned, in accordance with the DOM
CSS2 specification - you should directly access the longhand
properties (e.g. background-color) to access the desired values.
Example (ruby)
Since I have only done selenium-webdriver in ruby, I can only give a ruby example (idea is the same though the api is slightly different):
require "selenium-webdriver"
driver = Selenium::WebDriver.for :firefox
driver.navigate.to "http://yourpage.com"
element = driver.find_element(:id, 'id')
puts element.css_value('color')
I have my script.js into the folder script.
I'd like to manage, into that script, some C# variable, from a Web Form (e.g. <%= myString = 3 %>).
I think this is not possible, but maybe can I do it in some way? Thank you
Javascript is client side executed code, and C# is server side executed code. So you can't strictly make a "variable" visible, as they're two completely different code platforms/runtimes, running on two different computers. However you can still marshal the data between them in a few different ways.
Write a web service and call it via AJAX
Populate a control or your URL for your page with your data, and query it via the Javascript DOM API (or via some wrapper library like jQuery)
An example of the 2nd (since you asked):
<!-- Somewhere in your page -->
<span style="visibility:hidden" id="myData"><%= myString %></span>
// In Javascript, using jQuery:
var myData = $('#myData').text();
If the variable is directly related to a particular element on the page then you should definitely consider using the HTML5 data-* attributes to store the value. Imagine the variable pertains to the an anchor element, you could output like so:
Blah
You can then access the variables with jQuery like so $("#myLink").data("myVar") (note the camel case). jQuery will attempt to convert value to the correct type. If you want the raw value then just use the attr jQuery method like this $("#myLink").attr("data-my-var") (note the attribute name has not changed).
Alternatively you could do the following in your server-side code to output to your page:
<script type="text/javascript">
var myVar = <%= someVariableToOutput %>;
</script>
As long as this code is output above your dependent script it will be accessible as with any other JS variable.
Finally, you could execute an AJAX request when the page is loading and get the variable that way (though this may not be applicable if the data is only available during the main request)
Hope that helps
I am very new to Selenium, so my apologies if it's a silly question.
I have successfully wired up IntelliJ (Play! framework) with Selenium, and created some tests using firefoxDrivers.
I'm trying to check if the page had been validated properly.
long story short, I'm selecting an element like this:
WebElement smallDecel = firefoxDriver.findElement(By.cssSelector("#configTable tr:nth-child(2) td .playerDecelInput"));
I do some further operations (clear and change the value, submit the 'form'), and then I want to check if the TD the input sits in was given another class.
So, the question is - is there a simple technique I can use to find out if a WebElement / DOM has a class specified?
To expand on Sam Woods' answer, I use a simple extension method (this is for C#) to test whether or not an element has a specified class:
public static bool HasClass( this IWebElement el, string className ) {
return el.GetAttribute( "class" ).Split( ' ' ).Contains( className );
}
Once you find the element, you can just call myElement.GetAttribute("class"). Then you can parse the string that is returned and see if it contains or does not contain the class name you care about.
You can use FindElement(By.ClassName(//name of your class)); I would recommend that you either loop through and search the DOM for a set period of time or set a Thread.sleep(xxxx) and then look for the appended class.
I'm an Information Architect and JavaScript developer by trade nowadays, but recently I've been getting back into back-end coding again. And, whilst trying to get an HTML prototype integrated and working with our C#-based CMS, I've come to blows with our programmers over the HTML ID attributes being arbitrarily rewritten by .NET for form elements.
I can understand the code-behind reasoning for .NET changing IDs, but the fact you can no longer use IDs when trying to develop e.g. jQuery enhanced interfaces is causing some friction. What can I do to work around this?
I've tried using the class attribute instead, but that's really crappy, not what it's meant for and doesn't get around that problem of .NET effectively changing rendered source on the fly. It also means that CSS is less useful now and less efficient to create and maintain.
Any tips or advice greatly appreciated--anything for a few less sleepless nights...
The short answer is no, with webforms the id can always be rewritten depending on the nesting of the element. You can get access to the id through the ClientID property, so you could set the ids into variables in a script at the end of the page/control then put them into jQuery.
something like this:
<asp:button id="ImAButton" runat="server">Click Me</asp:button>
<script type="text/javascript">
var buttonId = "<%=ImAButton.ClientId%>";
$("#"+buttonId).bind('click', function() { alert('hi); });
</script>
It's a hack I know, but it will work.
(I should note for the un-initiated, I'm using the Prototype $ get by id method there)
One method is to override the ID's manually:
public override string UniqueID
{
get { return this.ID; }
}
public override string ClientID
{
get { return this.ID; }
}
Rick Strahl wrote a blog post with some more information on that approach.
Look at ASP.Net MVC - it addresses the over-kill object hierarchies that ASP.Net generates by default.
This site is written in MVC (I think) - look at it's structure. Were I working on a new project right now I would consider it first
If you're stuck with basic ASP.Net then be careful overriding the ClientID and UniqueID - it tends to break many web controls.
The best way I've found is to pass the unreadable ClientID out to the Javascript.
You can extend .net controls and make them return actual id's when related properties are called.
ClientID is the id attribute and UniqueID is the name attribute of html elements. So when you create a textbox like the following and using this instead of the textbox in framework, you make id and name attributes render as the same as the server-side id.
public class MyTextBox : TextBox
{
public override string ClientID { get { return ID; } }
public override string UniqueID { get { return ID; } }
}
To use this new user control, basically register this control as you would do for a custom user control (you can do is in web.config so you won't have to do it in all your pages):
<%# Register Assembly="MyLibrary" NameSpace="MyLibrary.WebControls" TagPrefix="MyPrefix" %>
And use it like you would use a text box:
<MyPrefix:MyTextBox ID="sampleTextBox" runat="server" />
Personally, I use a set of methods I have developed for bridging the server-side ASP.NET "magic" (I have yet to use the MS MVC stuff yet) and my client-side code because of the munging of the IDs that happens. Here is just one that may or may not prove useful:
public void RegisterControlClientID(Control control)
{
string variableDeclaration = string.Format("var {0} = \"{1}\";", control.ID, control.ClientID);
ClientScript.RegisterClientScriptBlock(GetType(), control.ID, variableDeclaration, true);
}
So, in your server-side code you simply call this and pass in the instance of a control for which you want to use a friendlier name for. In other words, during design time, you may have a textbox with the ID of "m_SomeTextBox" and you want to be able to write your JavaScript using that same name - you would simply call this method in your server-side code:
RegisterControlClientID(m_SomeTextBox);
And then on the client the following is rendered:
var m_SomeTextBox = "ctl00_m_ContentPlaceHolder_m_SomeTextBox";
That way all of your JavaScript code can be fairly ignorant of what ASP.NET decides to name the variable. Granted, there are some caveats to this, such as when you have multiple instances of a control on a page (because of using multiple instances of user controls that all have an instance of m_SomeTextBox within them, for example), but generally this method may be useful for your most basic needs.
What I usually do is create a general function that receives the name of the field. It adds the usual "asp.net" prefix and returns the object.
var elemPrefix = 'ctl00-ContentPlaceHolder-'; //replace the dashes for underscores
var o = function(name)
{
return document.getElementById(elemPrefix + name)
}
With that you can use this kind of calls in jQuery
$(o('buttonId')).bind('click', function() { alert('hi); });
You definitely don't want to hard-code the asp.net-generated ID into your CSS, because it can change if you rearrange things on your page in such a way that your control tree changes.
You're right that CSS IDs have their place, so I would ignore the suggestions to just use classes.
The various javascript hacks described here are overkill for a small problem. So is inheriting from a class and overriding the ID property. And it's certainly not helpful to suggest switching to MVC when all you want to do is refactor some CSS.
Just have separate divs and spans that you target with CSS. Don't target the ASP.NET controls directly if you want to use IDs.
<div id="DataGridContainer">
<asp:datagrid runat=server id="DataGrid" >
......
<asp:datagrid>
</div>
If you're using jQuery then you have loads of CSS selectors and jQuery custome selectors at your disposal to target elements on your page. So rather than picking out a submit button by it's id, you could do something like:
$('fieldset > input[type="submit"]').click(function() {...});
I can see how the .NET system feels less intuitive, but give it a chance. In my experience it actually ends up creating cleaner code. Sure
<asp:button id="ImAButton" runat="server">Click Me</asp:button>
<script type="text/javascript">
var buttonId = <%=ImAButton.ClientId%>
$(buttonId).bind('click', function() { alert('hi); });
</script>
works fine. But this is suffers from not being modular. What you really want is something like this:
<script type="text/javascript">
function MakeAClick(inid)
{
$(inid).bind('click', function() { alert('hi); });
}
</script>
and then later with your code on the java side or the C# side you call MakeAClick. Of course on the C# side it makes more sense, you just ClientID in there.
Maybe this is the real problem with the code you are reviewing.
A much better approach would be to use the ClientIDMode and set it to static. You can even set it for a specific page or globally in the web.config file. Then you never have to deal with this issue again and your JQuery is much cleaner.
Top of page:
<%# Page Title="" ClientIDMode="Static" Language="C#" CodeBehind="..." Inherits="WebApplication1.WebForm2" %>
On control only:
<asp:Panel runat="server" ClientIDMode="Static"></asp:Panel>