MVC 4 data validation message increases width of my form - css

I am creating quite simple form for my model. I have generated scaffolded "Edit" view for it with validation. One validation is for "URL" type and it is causing me problems.
I have this in view:
<div class="editor-label">
#Html.LabelFor(model => model.Server)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Server)
#Html.ValidationMessageFor(model => model.Server)
</div>
This is css for #content section that contains everything rendered by View:
#content
{
border:solid;
border-width:thin;
position:relative;
margin-left: auto ;
margin-right: auto ;
text-align:center;
margin-top: 50px;
min-width:480px;
max-width:800px;
display:table;
padding: 30px;
}
When page is loaded, #content is 480px wide and elements inside take up as much space as possible (editor-field elements and element with submit buttons are set to 100%, nothing else has width set in css).
When "required" validation message is displayed on fields, everything works ok (width doesnt change).
When I enter invalid URL, message is longer (localized version of default mesage says "Pole Server neobsahuje plnÄ› kvalifikovanou adresu URL protokolu http, https nebo ftp.") and the whole #content width changes to 657px;
Is there a way how I can keep the width as it was before validation message got displayed and wrap validation message in case it is too long into more than one line with css settings?
I would like to avoid fixed width settings (on main section and all elements including validation message divs) and still keep the layout template and its css universal so I can keep using it repeatedly without need for tailoring it to particular scenario where it is used.
Thanks in advance
I have included screenshot that shows how it looks like

Related

Sign In With Google button responsive design

Is there any way to make the new "Sign In With Google" button responsive? Specifically, vary the width based on the width of the containing element? I'd really just like to set the width to 100%.
I'm aware I can set the data-width attribute but this sets it to an explicit width and doesn't update if you change it after the initial script load - you have to reload the whole script to resize the width.
This isn't a perfect solution but it works for us. We're using Twitter Bootstrap.
The new JavaScript library has a renderButton method. You can therefore render the button multiple times on one page passing different widths to each button using something like this (400 is the max width allowed by the library)
private renderAllGoogleSignInButtons(): void {
this.renderGoogleSignInButton(document.getElementById('google-signin-xs'), 400);
this.renderGoogleSignInButton(document.getElementById('google-signin-sm'), 280);
this.renderGoogleSignInButton(document.getElementById('google-signin-md'), 372);
this.renderGoogleSignInButton(document.getElementById('google-signin-lg'), 400);
this.renderGoogleSignInButton(document.getElementById('google-signin-xl'), 400);
}
private renderGoogleSignInButton(element: HTMLElement, width: number){
const options {
type: 'standard',
....
width: width
};
google.accounts.id.renderButton(element, options);
}
We then use the display classes from bootstrap to hide/show each button depending on the size.
<div class="mx-auto" style="max-width: 400px">
<div class="d-none-sm d-none-md d-none-lg d-none-xl">
<div id="google-signin-xs"></div>
</div>
<div class="d-none d-none-md d-none-lg d-none-xl">
<div id="google-signin-sm"></div>
</div>
<div class="d-none d-none-sm d-none-lg d-none-xl">
<div id="google-signin-md"></div>
</div>
<div class="d-none d-none-sm d-none-md d-none-xl">
<div id="google-signin-lg"></div>
</div>
<div class="d-none d-none-sm d-none-md d-none-lg">
<div id="google-signin-xl"></div>
</div>
</div>
We use a wrapper container with mx-auto and a max-width to center the buttons but you don't have to do this.
Our actual implementation is slightly different than the above as we're using Angular and the button is a component but you can get the idea from the above.
The only drawback with this method is that the "personalized button" doesn't seem to display for all rendered buttons but it doesn't seem to affect their functionality.
This answer is based on the new Google Identity Services.
You could try listening for a resize in the window using the resize event, then re-render the Google Sign In button on change. The assumption here is that the container will respond to match the window size:
addEventListener('resize', (event) => {});
onresize = (event) => {
const element = document.getElementById('someContainer');
if (element) {
renderGoogleButton(document.getElementById('googleButton'), element.offsetWidth); // adjust to whatever proportion of the "container" you like
}
}
renderGoogleButton(element, width) {
const options = {
type: 'outline',
width: width
}
google.accounts.id.renderButton(element, options);
}
I've also had better results when the button is centered, not left aligned. The following in Bootstrap:
<div class="d-flex justify-content-center">
<div id="googleButton"></div>
</div>
NB: The max width for the Google button as of the time of writing is 400px, so bear that value in mind as the limit.
I did a workaround, and it worked for me. As I needed the button to have 100% width in mobile devices.
If you have another element on the screen that behaves the same way you need (like having its width 100%), you can select it using a querySelector, and get its width element.clientWidth, after this you can pass the width to the renderButton function provided by google.
But this solution is not valid if you would like the button to change its size on resizing.
I used transform: scale like this in the CSS:
.sign_in_btn_wrapper {
transform: scale(1.5, 1.5);
float: left;
margin-left: 20vmin;
font-weight: bold;
}
Then, instead of wrapping it as I intended, I found that it was fine to just add the class directly to the goog div:
<div class="g_id_signin sign_in_btn_wrapper"
data-type="standard"
data-shape="rectangular"
data-theme="outline"
data-text="signin_with"
data-size="large"
data-logo_alignment="left"
data-width="250">
</div>
By fiddling with combinations of data-size and data-width, along with the scaling factors, I was able to make it the size I wanted. You can use CSS media queries to adjust the 'transform: scale' values so that it is 'Responsive' to the display size of the user's device. You could also use other trickier methods by having JS tweak variables in your CSS that are then used to set the scaling factors.
Good luck. You'd think it'd be in the interest of these big 'sign in with' providers to get together a coordinating working group to make it easier for web site developers to make all the sign-in buttons the same damn size -- you know they'd rather not have their button come out smaller, and pages look better when things are uniform. And what's with only having dimensions in pixels? At least give us vw, vh, and my favorite: vmin. (Using vmin to set things like font size means you can often skip more tedious RWD contortions and call it good enough.) </end_rant>

how to make screen reader read document loading and document loaded?

What to do so that screen reader reads document loading while loading the document and document loaded when document component gets loaded in react?
Adding aria-busy="true" and aria-hidden="true" attributes to the component while loading will hide the content from screen readers temporarily.
For the announcement, somewhere else, create a <div role="status"> and add/remove child elements to it that will be announced when loading/loaded.
End result:
<main>
<Document
aria-busy={isLoading ? 'true' : null}
aria-hidden={isLoading ? 'true' : null}>
</Document>
<div role="status" class="visually-hidden">
{isLoading ? (
<span key="loading">
Document loading
</span>
) : (
<span key="loaded">
Document loaded
</span>
)}
</div>
</main>
The key props are there to make sure React doesn't reuse the same <span> element.
The .visually-hidden class makes it invisible except to screen readers:
.visually-hidden {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
You will need to see how to do the following in React, but the principles for AJAX page loading carry across to all SPAs.
The only difference between this and what you asked for is you don't announce "document loaded" instead you focus the <h1> on the page as that is more useful to screen reader users.
Before Loading
You need to signal to a user that a page is loading if you are using a SPA pattern (and therefore interrupting normal navigation).
e.g. I click your link you need to let me know that an action is being performed (loading.....) as you intercept the normal browser behaviour with e.preventDefault() or equivalent.
The simplest way is to use aria-live=assertive on a region that explains the page is loading.
You may want to visually hide this aria-live region (so that only screen readers can access it) so I have included a class to do this in the snippet below, however for the demo I have left the region visible. Here is a link to my original discussion on why to use this class to hide content.
After Loading
Additionally when the new page loads you need to manage focus.
The best way to do this is to add a level 1 heading (<h1>) to each page that has tabindex="-1".
Once the page loads the last action you perform in your JavaScript navigation function is to place the focus onto this heading and then clear the aria-live region
This has two benefits:
it lets the user know where they are now
it also lets them know when the page load is complete (as AJAX navigation doesn't announce when the page is loaded in most screen readers).
By using tabindex="-1" it means that the heading won't be focusable by anything other than your JavaScript so won't interfere with the normal document flow.
Example
var link = document.querySelector('a');
var liveRegion = document.querySelector('p');
var originalPage = document.querySelector('.currentPage');
var newPage = document.querySelector('.newPage');
link.addEventListener('click', function(e){
e.preventDefault();
liveRegion.innerHTML = "loading";
simulateLoading();
});
//this function simulates loading a new page
function simulateLoading(){
window.setTimeout(function(){
//this bit just hides the old page and shows the new page to simulate a page load
originalPage.style.display = "none";
newPage.style.display = "block";
//////////////ACTUAL CODE/////////////////
// grab the heading on the new page (after the new page has loaded fully)
var mainHeading = document.querySelector('.newPage h1');
//focus the main heading
mainHeading.focus();
// reset the aria-live region ready for further navigation
liveRegion.innerHTML = "";
}, 1000);
}
.newPage{
display:none;
}
<div class="currentPage">
<h1>Current Page</h1>
Click me to navigate
<p class="live-region visually-hidden" aria-live="assertive"></p>
</div>
<div class="newPage">
<h1 tabindex="-1">New Page Heading Focused Once Loaded</h1>
<button>Just a button for something to focus so you can see you can't refocus the H1 using the Tab key (or shift + Tab)</button>
<p>Below is the visually hidden class I mentioned, this can be used to hide the aria-live region visually if you wish, I have left it visible for demonstration purposes.</p>
<pre>
.visually-hidden {
border: 0;
padding: 0;
margin: 0;
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 - a 0 height clip, off to the bottom right of the visible 1px box */
clip: rect(1px, 1px, 1px, 1px); /*maybe deprecated but we need to support legacy browsers */
clip-path: inset(50%); /*modern browsers, clip-path works inwards from each corner*/
white-space: nowrap; /* added line to stop words getting smushed together (as they go onto seperate lines and some screen readers do not understand line feeds as a space */
}
</pre>
</div>

Css print : page margin conflicts with fixed title

I am looking for a way to set a print-devoted css that shows a fixed title on every page.
Unfortunately, I couldn't manage to print this title nicely on the 2nd page, since it always "walks on " the table, ignoring declared body padding / margin ... though I am quite sure the body is not suited here, I couldn't find any working way.
Any idea?
<h2 id="tableTitle">Fixed title</h2>
<button class="noPrint" onclick="myFunction()">Print this table</button>
<table>...content fitting at least 2 pages ...</table>
...
body{
margin-top:100px;
}
#tableTitle {
position: fixed;
top : 0;
}
Here's the fiddle

Watir webdriver_Unable to change dropdown list in one field and verify value change in another field

Frustrated new user having difficulty. Tried many variations and just cannot get it to work. The html is below and I've stripped out the extra lines. The test has to be written using this html, I cannot change it. Note, classes are named "span3".
This is a popup window that is NOT a new window, it just appears to be a new window. The top "span3" is a dropdown list and I am trying to change the selection. I tried using the select_list in watir, but that did not work.
In the bottom "span3", the grossmarginpercent value will be updated when I change the dropdown value in the top "span3". I want to confirm that grossmarginpercent is updated to the correct value.
I've included the last script I tried. I added a put because I wanted I seeing '2' on the screen, watir was returning false, and I wanted to see what watir was seeing.
watir script:
grossmarginpercent = browser.div(:id => "target_modal").div(:class => "modal_body").div(:class => "row").div(:class => "span3", :index => 1).label(:id => "GrossMarginPercent")
puts grossmarginpercent.value
puts grossmarginpercent.value.include? '2'
html:
<div class="modal-body">
<div class="row">
<div class="span3">
<label>Reward Type</label><select data-bind="options: $root.RewardOptions, optionsText: 'DisplayName', value: RewardOptionId, optionsValue: 'RewardOptionId'"></select>
</div>
<div class="span1"></div>
<div class="span3">
<label>Gross Margin Percent</label><label id="GrossMarginPercent" data-bind="formattedNumber: { value: GrossMarginPercent, format: '#,###.##%' }" style="padding: 6px 4px 8px 0px;"></label>
</div>
</div>
</div>
This is a bit of a stab in the dark, but I would try using Element#text instead of Element#value:
puts grossmarginpercent.text
puts grossmarginpercent.text.include? '2'
I am making a couple of assumptions:
Given the "data-bind" attributes, I am guessing that you are using KnockoutJS (as that seems to be the most popular search result when I looked for people using data-bind attributes).
formattedNumber is a custom binding that is setting the text of the label. I assume you are trying to check something you see, which for a label element would be its text rather than its value attribute.

Scriptaculous Effect.Appear glitch onmouseover

I've got a problem when using scriptaculous Effect.Appear() as a menu option, I wanted to create a flash-like menu but with pure css and scriptaculous.
I've got my desired outcome which is when I hover over a box, a text (with display: none;) appear above it and the box changes height and background color. Now the problem is that when my mouse move extremely fast and crazy over the box, the text remains (as if it was selected).
What I want is that as I hover the text appear, and if my mouse of out, the text disappear.
My codes
function ShowEffect(element){
new Effect.Appear(element,
{duration:0.3, from:0, to:1.0, queue: 'front'});
}
function HideEffect(element){
new Effect.Appear(element,
{duration:0.2, from:1.0, to:0, queue: 'end'});
}
The Divs
<div class="lefty" style="width: 90px; margin-right: 2px;">
<div style="display: none;" id="clicker2text">ABOUT US</div>
<div style="width: 90px;" onmouseover="ShowEffect('clicker2text')" onmouseout="HideEffect('clicker2text')"></div>
</div>
Any help is appreciated :)
Instead of using the onmouseover attribute on the div use an event observer like this
$$('.lefty').invoke('observe','mouseover',ShowEffect);
$$('.lefty').invoke('observe','mouseout',HideEffect);
But I think this will work better as you are watching for the events that bubble up to body and then acting on it if is the right element.
$$('body').first().observe('mouseover',function(e){
if(e.findElement().hasClass('lefty'))
{
ShowEffect(e.findElement());
}
else
{
//trigger for all of the menus just to make sure the are hidden
//instead of stuck on
$$('.lefty').each(function(element){
if(element.visible())
{
HideEffect();
}
});
}
});
This should give you some ideas - see if it solves your problem.

Resources