Trying to use kendo-mobile-switch inside kendowWindow. The switch is displayed fine, but doesn't toggle. On the same page with the same included kendo css/js the same mobile switch toggles just fine if used on the page itself, not inside the kendoWindow.
I've looked in the page source and it looks like when switch does toggle, the following transformation is added:
<span class="km-switch-handle" style="transform: translateX(27px) translateY(0px);">
The same switch in the "non-toggled" state looks like this:
<span class="km-switch-handle" style="transform: translateX(0px) translateY(0px);">
However, if I look at the source of the toggle inside kendoWindow, in both toggled and non-toggled states it looks like this:
<span class="km-switch-handle" style="transform: translateX(0px) translateY(0px);">
I've also dogged through kendo.all.js and it looks like when switch is toggled, it computes the offset it needs to transform itself based on the position. My guess is when displayed in the kendoWindow, get position logic fails/doesn't work properly:
_position: function (position) {
var that = this;
that.position = position;
that.handle.css(TRANSFORMSTYLE, 'translatex(' + position + 'px)');
if (that._animateBackground) {
that.background.css(MARGINLEFT, that.origin + position);
}
},
Any idea what the problem might be?
Guess I'm going to answer my own question:
Found a very similar issue when mobile switch is used inside the list view:
http://www.telerik.com/forums/angular-kendo-mobile-switch-in-list-view-template
The switch in this example behaves exactly the same as it does in kendoWindow. Judging by the title of the issue, the problem was with "angular compilation is performed before the items are inserted into the DOM". This would explain why position is not calculated in the case with kendoWindow.
Related
We have a Kendo TreeList that works fine. Data shows, everything shows in the hierarchy correctly. The problem is, we need to group each two columns into another "superset" group.
The column headings (the names above are not real) are too long if not grouped as shown, and they lose useful context.
I tried adding an HTML table above the TreeList, but that doesn't look right. And it doesn't work if the user resizes the columns. Also the toolbar (for Excel export) is in the way, so it doesn't even look like it's part of the TreeList.
I also looked at wrapping the text in the columns, but from what I've seen, that's really iffy too.
It seems like an extra row as shown above (with the ability to merge some columns, like with an HTML table) is the best way to go. Despite scouring the web, I couldn't find a way to do this. Is this even possible with a Kendo TreeList?
This has been solved. Not by me, but by another developer on our team who's insanely good at JavaScript.
The trick is to edit the TreeList's HTML and CSS through JavaScript. You can bind to any event, but we do it on page load:
<script>
$(document).ready(function () {
// anything in here will get executed when the page is loaded
addTopRowToTreeList();
});
function addTopRowToTreeList() {
// grab the thead section
// your HTML may be different
var foo = $('#MyTreeList').children('div.k-grid-header').children('div.k-grid-header-wrap');
var tableChild = foo.children('table');
var headChild = tableChild.children('thead');
var bottomRow = headChild.children('tr');
var topRow = $('<tr>').attr('role', 'row');
// bottom cell should draw a border on the left
bottomRow.children('th').eq(0).addClass('k-first');
// add blank cell
var myNewCell = $('<th>').addClass('k-header').attr('colspan', '1')
var headerString = '';
var headerText = $('<span>').addClass('k-link').text(headerString);
myNewCell.append(headerText);
topRow.append(myNewCell);
// ... add remaining cells, like above
headChild.prepend(topRow);
}
</script>
That's all there is to it!
I'm trying to set the background-color of a Select element to the background-color of it's selected Option like so:
YUI().use('selector-css3', 'node', function(Y) {
function set_color( e ) {
this.setStyle('backgroundColor',this.one('option:checked').getStyle('backgroundColor'));
};
Y.on(['available','change'], set_color, '#id_linkcolor');
});
Strangely this works perfectly in Chrome. In FF however it seems to always revert to a specific color. Even more weirdly, this:
this.setStyle('backgroundColor',this.get('options').item(3).getStyle('backgroundColor');
does seem to work. But when I use the selectedIndex to retrieve the selected option it doesn't work anymore.
Check it out here: http://jsfiddle.net/9sy02756/4/
Thanks!
UPDATE
I decided to approach this differently like this:
function set_color( e ) {
this.set('className','');
this.addClass( 'linkcolor_'+this.one('option:checked').get('value') );
};
This way the parent SELECT element just gets assigned the same class as the selected child OPTION and css takes care of the rest. Probably a cleaner solution anyway.
http://jsfiddle.net/9sy02756/6/
In your code, when you do this.one('option:checked').getStyle('backgroundColor'), YUI uses the window.getComputedStyle method.
In Firefox, getting the background color on an <option> returns the hover color, which turns out to be a very nice blue. And it will remains that way until you open the select again.
The only way around this is to store the color during <option>'s mouseenter event, and apply it during change. But mouseenter on <option> are only triggered in firefox, not chrome nor IE.
In the end you will need a mix of both approaches to get it right. So the question is answered, the mystery solved, but the alternative approach you proposed in the edit is way simpler.
YUI().use('node', 'selector-css3', function(Y) {
var lastColor;
function set_color(e) {
this.setStyle('backgroundColor', lastColor || this.one('option:checked').getStyle('backgroundColor'));
};
Y.on(['available', 'change'], set_color, '#id_linkcolor');
// For firefox, store computed color before default select blue is applied
Y.on("mouseover", function(e) {
lastColor = e.target.getStyle('backgroundColor');
}, '#id_linkcolor option');
});
http://jsfiddle.net/fxaeberhard/hy3okdph/
The excellent dropdown jQuery UI Multiselect widget that supports styling via jQuery UI Themeroller still doesn't have support for including images within the drop down rows.
I didn't see any answers to this problem within Stackoverflow yet it seems to be asked regularly in various areas of the internet, so I am giving the answer to this question below..
(ALSO See my FIDDLE Example to see this in action,)
The following is based on an initial idea by 'pdlove' for introducing the use of images within this excellent UI Multiselect for jQuery.
Adding Image support for line items in check box text area is achieved by setting out the selector option rows html like this:
<option value="somevalue" image="yourimage.jpg" class="multSelktrImg">
normal visible text
</option>
I would also add a class control to your style sheet css file to set the image size being rendered in the option line items of the drop down, along with a couple of position settings for the image, label and span text.
In this example I use the class name 'multSelktrImg', so within the css file it would look something like this:
.multSelktrImg span{position: relative;top: 10px;vertical-align: middle;
display: inline-flex;}
.multSelktrImg input {vertical-align: -2px;}
.multSelktrImg img {position: relative;height: 30px;margin: 2px 6px;top: -10px;}
Now for the change in the src/jquery.multiselect.js file
Search for the following matching code around line 130 (depending on what version id of the script you are using):
// build items
el.find('option').each(function( i ){
var $this = $(this),
parent = this.parentNode,
title = this.innerHTML,
description = this.title,
....
ADD the following line above "title = this.innerHTML,":
image = this.getAttribute("image");
so that it looks like this:
// build items
el.find('option').each(function( i ){
var $this = $(this),
parent = this.parentNode,
image = this.getAttribute("image");
title = this.innerHTML,
description = this.title,
Now Search for the following matching code around line 180:
// add the title and close everything off
html += ' /><span>' + title + '</span></label></li>';
....
Replace the code line with the following to allow for rendering of your images:
// add the title and close everything off
html += ' /><span>';
if (image != null) {
html += '<img src="'+image+'" class="multSelktrImg">';
}
html += title + '</span></label></li>';
save the new version of the script src/jquery.multiselect.js file and now the images will appear in the multiselect drop down. Use the 'multSelktrImg' class value to control the size of the image displayed by altering the pixel size for the class in your css file.
In the FIDDLE version, I have altered the minimized version of the jQuery script, and created an initialisation of the Select object.
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.
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!