Trying to alternate css code based on condition in URL path - asp.net-mvc-3

I am trying to alternate a CSS class in a <fieldset>. Normally a #helper function would work fine (see the #helper below), however I have two (2) circumstances that won't allow it to work properly.
First, I am using a Input.Edit.cshtml field template in ~/Views/EditorTemplates/Fields.
This basically means that as I build up a form, the Input.Edit.cshtml file is being called each time for as many <input>'s as I have in my form.
Second, I am using a condition to check the path of the URL in order to only apply this CSS alternating class on pages below a certain path. Specifically, I want to apply this change to pages under my ~/Services path. On all other pages I do not want the change applied. I check this condition using Request.Url.AbsoluteUri as you see below.
This is where I think my problem lies, as the alternating code is applied but then because it is called again for the same condition on the same page it is applied incorrectly due to my logic.
Now it could be that I am just stuck with the problem.
Here is the code:
#{
string CurrentUrl = Request.Url.AbsoluteUri;
}
#helper ResponsiveCss(string cssClass)
{
if (ViewBag.count == null) { ViewBag.count = 0; }
<text>class="#(ViewBag.count % 2 == 1 ? cssClass : "one-half last")"</text>
ViewBag.count++;
}
#if (CurrentUrl.Contains("Services"))
{
<fieldset #ResponsiveCss("one-half")>
//Label and Input code
</fieldset>
}
What should happen is that the class="one-half" is applied on the first <fieldset> that is created in the form, and then class="one-half last" on the second that is created.
Instead what is happening is that class="one-half" is NOT being applied on the first <fieldset> that is created, but rather ALL <fieldset>'s are being created with class="one-half last".
Sorry if that is not clear. Any thoughts on if I can make this work given the circumstances (and how)? Thanks.

Hopefully this solves your problem.
Alternating style
Instead of alternating the class name, you can use the nth-of-type or nth-child pseudo-classes.
fieldset:nth-of-type(odd) {}
fieldset:nth-of-type(even) {}
See this example: http://jsfiddle.net/cx9UG/
Note: These pseudo-classes can also be used in JQuery selector and document selector (querySelector and querySelectorAll)
CSS depending on URL
This is really CSS depending on the view. Just create two CSS bundles then apply in to the appropriate views.
View with alternating style #Styles.Render("~/Content/alternating")
View without alternating style #Styles.Render("~/Content/mono")
The EditorTemplate should not need to know the URL.

Related

In the Magellan / Nightwatch framework, how to set a CSS outline on an element?

Suppose in writing or verifying a test, the command code is:
pToggleMyCoolToggle: function () {
var selectors = this.elements;
return this
.getEl(selectors.myCoolCheckbox.selector)
.moveToEl(selectors.myCoolCheckbox.selector)
.clickEl(selectors.myCoolCheckbox.selector);
}
How can this element on the browser be shown with an outline using CSS:
outline: 3px dotted orange
by adding some code to the above command, using the methods inside of Magellan / Nightwatch?
Just use .execute
client.execute(function(){
document.getElementById('idYouWantToTarget').style.border="3px dotted orange";
})
I just found that the name selectors.myCoolCheckbox.selector is written by some amateur. It really should be paymentPage.useCreditCardRadio.selector. So the final selector states what the CSS selector is.
The line selectors = this.elements is very misleading too. selectors is not the "elements". It might be paymentPage = this.elements and paymentPage has many properties, including a useCreditCardRadio. Or it could be paymentPageElements = this.elements which means paymentPageElements is an object that contains all elements. So this example shows how bad naming affects programming, for all the people who will need to touch or edit the code in the future.
As a result, you should be able to use
var el = document.querySelector(paymentPage.useCreditCardRadio.selector);
and once you have the element, you can add the outline to it.

MvcContrib Pager - Change Page Size

I'm not using a Grid, just using the MvcContrib Pager. I have a partial view created for the Pager (so I can display it at top and bottom of the results easily), and it calls the #Html. Pager method as so:
#Html.Pager(Model.PagedPrograms).First("<<").Last(">>").Next(">").Previous("<").Format("Item {0} - {1} of {2} ")
This works without additional tweaking as long as all parameters are passed to the page via QueryString, since Pager knows to rebuild those back on the URLs.
I'd like to give the user the option to change the page size (say 20, 50, All) ... I can easily handle that on the controller end, and I could write something like
#if (Model is Foo) {
#Html.ActionLink<SearchController>(sc => sc.Foo(var1, var2, var3, 20), "20")
#Html.ActionLink<SearchController>(sc => sc.Foo(var1, var2, var3, 50), "50");
#Html.ActionLink<SearchController>(sc => sc.Foo(var1, var2, var3, -1), "All");
}
But I would have to do that for each Model type that might use this Pager... I might be overthinking this or coming at this completely backwards, but I thought I'd ask and see if anyone had insight.
Currently the Pager is only called from a view which takes IPagedProgramList (provides IPagination<ProgramDTO> { get; }), and I have two ViewModels implementing that interface (a simple search and an advanced search). But if this project grows and we add new ViewModels that use that Interface I would have to update the Pager partial view, and that seems bad / doesn't scale / etc.
So a nod to Ek0nomik who got me thinking outside the box on this one.
Step 1: Make sure all pages that are going to use the Pager controller are passing all parameters via GET not POST. Use RedirectToAction if you must accept post somewhere and just translate all the parameters into primitive types for the GET method.
Step 2: Don't worry about adding .Link() to the Pager. As long as everything's coming in via GET, you're fine. It will look at the URL for the page and adjust the page number parameter as it needs to when you're going forward/back.
Step 3 (optional but recommended): For consistency across your application, somewhere (probably your Global.ascx.cs file) you should define a list of the page sizes you will support. In my case I used Dictionary<int,string> so that I could pass -1 as the PageSize value but display All (and of course the data layer must know that -1 means disable paging).
Step 4: Add something like this to your pager partial view:
<ul class="pageSizeSelector">
#foreach (KeyValuePair<int,string> kvp in MvcApplication.AVAIL_PAGE_SIZES)
{
<li>#kvp.Value</li>
}
</ul>
Step 5: The javascript function changePageSize is so simple, I couldn't believe I hadn't thought of this first (note: no jQuery required... just in case you're not already using it, you don't need to just for this).
function changePageSize(size) {
var PSpattern = /PageSize=\d+/i;
var url = window.location.href;
url = url.replace(PSpattern, "PageSize=" + size);
window.location.href = url;
}
Step 6 (optional, unless you're an Internet Troll): Profit!

jqgrid: How to format master/detail grids?

I have a jqgrid with a subgrid.
I am attempting to apply different colors to master and detail grids. I have two rules: the first one is to alternate odd and pair colors and the other one is to apply specific CSS to the row, based on values of a specific field.
Both master & details grid, contains the following gridComplete functions, where obviously childnodes index varies cause tables contains different fields:
gridComplete: function () {
var _rows = $(".jqgrow");
for (var i = 0; i < _rows.length; i++) {
_rows[i].attributes["class"].value += " " + _rows[i].childNodes[4].textContent;
_rows[i].attributes["class"].value += " " + _rows[i].childNodes[4].innerText;
}
applyZebra("jqTicketgrid");
}
applyZebra function provides to alternate odd/pair colours and has already been tested on another grid which not contains a subgrid.
For the record, I found above solutions in other solved questions of this forum, and both works with "simple" jqgrids (not master/detail).
PROBLEM
The master grid is formatted only when I click to expand the detail rows, while detail subgrid never alternate colours, neither apply format based on cell contents...
Where I am wrong? Pheraps I must intercept another event which is not gridComplete? Otherwise with grid&subgrids it's impossible to use _rows[x] & childNodes[y] attributes?
Please ask for clarifications, if needed, thx.
Thanks in advance!
I suppose the error in your code is that you use $(".jqgrow") instead of $(".jqgrow", this) where this inside of gridComplete will be either DOM element of the <table> of the grid or the subgid (I suppose you use grid as subgrid).
Additionally I would not recommend you to use you current code at all. It's much more effective and simple to to use cellattr. The rawObject parameter allow you access all other cells of the current row. In the answer you will find an example of implementation.

Big switch in the view

I'm new to MVC and php framework, so please excuse me for this simple question...
I like to have my views without big chunk of php code but I have a case where I don't really know how to do it properly.
Basically some object has 20+ different states and the state is given by the model.
Now I have a :
switch($object->getState())
{
case 0:
$sText = '...';
break;
case 1:
$sText = '... on the'.$object->getDate();
break;
...
case 20:
$sText = '...';
break;
}
?>
<img src="<?echo $object->getState()?>.png" alt = "<?echo $sText;?>"
title = "<?echo $sText;?>" />
How can I do that without the 40+ lines of php in the view ? I don't want to have to repeat the <img> tag 20 times. For me the text should belongs to the view, not the model.
Maybe a view helper that will assign the text to the state ?
A view helper isn't going to make your code any less ambiguous or better MVC. The text for the view might not belong to the Model, but the logic for determining the text definitely doesn't belong to the view. There's nothing wrong with writing a method like $model->getViewTextForState($object->getState()) - that's basically the same approach as you'd use for string localization for numerous languages.
Think of it this way - the alt text for the view really does belong to the model because the model is responsible for marshalling ALL of the data. If some text in the view is variable, then it is literally model data, just like the image name you're producing from the $object->getState() method. The image name and the alt text for it are data and should be provided to the view from the model with a single line access method
The switch could be in your action, and you could use translation strings like this
$this->sText = 'object_state_' . $object->getState()
then in your view, translating $sText would do the trick.

Templating issues with Backbone.js views : this.el attributes

I'm trying to find the best way to render a li-element :
I've read that i should never replace this.el
So it seems that i have to unwrap my template in my LiView render() function :
// replace element content with html generated from template
var $rendered = $.tmpl(this.template, this.model.toJSON());
this.el.html($rendered.unwrap().html());
I just get the contents inside the $rendered li, since i should not replace it.
But how should i transfer attributes ?
I tried :
this.el.attr('class', $rendered.attr('class'));
this.el.attr('title', $rendered.attr('title'));
But it replaces attributes... And some (like jQuery ui ui-draggable) could be lost.
All this seems a bit clunky...
Thanks !
I'm not sure I fully grasp what you're trying to do Olouv, but I'll have a stab at answering your question regardless :)
You have an liView that corresponds to an li dom element
So you need to specify
el: "li"
Do not have an li in your template. Then the result of your render will be
<li>
contents of template
</li>
Now you want to add attributes to this li element?
Class names are pretty simple, just add the className attribute to your view
className: "ui-draggable myGreatClass ui-corner-all"
If you need to add additional attributes to your root (li) element
$(el).attr("title","your title")
If that doesn't work for you, and you want to put the li attributes in your template perhaps consider some form of the following:
Tolerating HTML of the form:
Instead of an liView (list item view), just have a ulView (List view), and put a loop construct in your template

Resources