To allow my users to pick their colour scheme of my site, I decided to add a "Settings" page that lets them pick their colours. The simplest way to choose a colour that I could think of was to let them type a colour's name, and have the text they enter fed directly into the CSS of the elements. This code shows the idea.
var saveButton = document.getElementById('saveButton');
var saveBox = document.getElementById('textToSave');
var colourBox = document.getElementById("colourBox");
saveButton.onclick = function() {
colourBox.style.backgroundColor = saveBox.value;
}
#colourBox {
display: inline-block;
background-color: grey;
height: 100px;
width: 100px;
}
input {
margin: 0px;
}
input,
Button {
height: 30px;
font-size: 15px;
margin-left: 10px;
margin-right: 10px
}
<input id="textToSave" type="text">
<button id="saveButton">Save</button>
<br>
<div id="colourBox"></div>
Since I'm directly feeding user input into the element though, I'm worried this might open my site up to an injection attack.
I know very little about exploits though. The best I could do to attempt an injection attack was to enter the following "colour" into the text box:
yellow; width: 200px;
But the second statement was dropped, likely because I'm specifying in the JavaScript that I'm changing the background colour, and not the style in general.
Is the above fiddle susceptible to an injection attack?
I think this should be safe. You're not assigning to the style attribute in general, you're assigning specifically to element.style.backgroundColor. This doesn't get re-parsed as HTML or a CSS style string.
If it's not a valid color specification, it will just be ignored.
Note that this would not be entirely safe if you were doing this with an attribute that allows URLs, such as background-image. The user could then enter the URL for any remote site, and execute code there. This might allow for some kinds of XSS exploits.
Use <input type="color" />
Since JavaScript and CSS run on client side (browser), it can not be used to attack to your website back-end. The worst case is that a user breaks his own view, but a page/browser refresh will undo the bad view. I hope this addresses your question.
Related
My goal
What is available
This is done using a simple calendar input.
<input type="date">
I have tried reducing the width of the input, but then it doesn't seem elegant as it deforms in different browsers. The previous images were on chrome. Below is how it appears in Mozilla.
I think I could specify the width for each browser. That however seems inelegant and convoluted.
In most modern browsers you can use the showPicker() method of an input[type=date] element to make the widget appear.
So, with that in mind, you could move the <input> outside of a container with overflow:hidden and trigger the widget from a click event on another element.
Something like the snippet below might work, though I wouldn't really suggest using this in a public facing web app due to the limited support :
let cal = document.querySelector('label.calendar');
let ci = document.querySelector('label.calendar input[type=date]');
cal.addEventListener('click', event => ci.showPicker());
label.calendar {
overflow: hidden;
user-select: none;
cursor: pointer;
}
label.calendar input {
position: absolute;
bottom: 100%;
left: 0;
border: 0;
padding: 0;
outline: none;
}
<label class="calendar">
<input type="date">
<span>đź—“</span>
</label>
Instead, I would recommend you look into other (more mature) options like Smart HTML Calendar which is a Custom HTML Element.
What are you trying to achieve is not possible to do in one solution for every browser because the "date" input type is rendered by the browser and every one of them has their own specification on how to render things. You could try to use a custom component or plugin that renders a calendar using javascript/CSS/HTML that is the only way to have a consistent look and feel across different browsers.
I'm creating a web app and need to decide on a consistent way to style my elements. I noticed that a lot of help online uses classes but I have generally used attributes (like the query selector [my-attr]) to style multiple elements, since I don't have to work with classList and can remove and set attributes very easily.
Using no external libraries, why would people use classes to style their elements over attributes? It seems like attributes can do everything classes can do but better, since you can also assign values to the attributes as well. I also haven't seen any discussion on performance differences anywhere, making me believe that attributes should be more appreciated than they are in tutorials on styling pages.
Any thoughts on instances where classes could do a better job than attributes at something would be greatly appreciated, even if the arguments are subjective and come down to some sort of preference!
Thanks!
Again, this is for vanilla javascript, HTML, and CSS. I understand that libraries like jQuery may make it easier to use classes, but I don't plan on using any libraries.
It's more consistent, is the end-all be all, truthfully. If you'd rather use attributes, go for it. However it makes it just that much more difficult for anyone who has to help you out later. CSS classes are designed for grouped selection and application of common styles. CSS just happens to also be able to select attributes as well, because it does make sense in some edge cases.
Generally, attributes should be reserved for anything non-style related that adds a value for a different use, be it screen-readers or variable containers for JavaScript, such as data-id="34" may let you make an asynchronous request with the ID parameter.
Consider this example, it's got some simple "class" based buttons:
.button {
display: inline-block;
border: 1px solid;
padding: 4px 10px;
text-decoration: none;
margin-bottom: 4px;
}
.primary {
background: currentColor;
}
.primary span {
color: #fff;
}
.blue {
color: #0095ee;
}
.red {
color: #ee3300
}
Red Button
<span>Red Button</span>
<br />
Blue Button
<span>Blue Button</span>
To replicate something like this with attributes, we'll be doing something like this with some obnoxious and rather arbitrary attribute names. Doing this I actually messed up because I used the wrong attribute name and value pair in one case.
[type="button"] {
display: inline-block;
border: 1px solid;
padding: 4px 10px;
text-decoration: none;
margin-bottom: 4px;
}
[status="primary"] {
background: currentColor;
}
[status="primary"] span {
color: #fff;
}
[color="blue"] {
color: #0095ee;
}
[color="red"] {
color: #ee3300
}
Red Button
<span>Red Button</span>
<br />
Blue Button
<span>Blue Button</span>
Does it not make more semantic sense to keep all your stylistic and group target attributes inside the class attribute? I mean, that's what it was designed for. I suppose you could drop the parameter value and just use parameter names, but you're really defeating the purpose of attributes, considering class is a Global Attribute in and of itself.
Here's a JavaScript example as well:
let classes = document.getElementsByClassName('button');
for( i = 0, n = classes.length; i < n; ++i ){
classes[i].style.background = 'red';
}
let attrs = document.querySelectorAll('[button]');
for( i = 0, n = attrs.length; i < n; ++i ){
attrs[i].style.background = 'blue';
}
a {
padding: 10px;
margin-bottom: 4px;
display: inline-block;
text-decoration: none;
color: #fff;
}
<a href="#" button>Attr 1</a>
<a href="#" button>Attr 2</a>
<a href="#" button>Attr 3</a>
<br />
Class 1
Class 2
Class 3
Putting aside the fact that JS has immense integration with class (and id) based functions for selectors, you have to use querySelector and querySelectorAll for the attribute buttons.
While not inherently a bad thing, (honestly I prefer querySelector over getElement(s)By… in general), but when you look at it, querySelectorAll('[button]') just does not read well, almost like I'm targeting a <button> element. Semantically it makes it harder to read than:
getElementsByClassName('button') - Clearly getting all elements that have a button class, or even
querySelectorAll('.button') - Since the . is universally understood as the "class" selector, and everyone working with HTML, CSS, and JS learns that on literally day 1 of any web development program/tutorial. So you're throwing a bit of a wrench into the project by removing such a fundamental piece of it.
I'm sure you've heard the phrase "Just because you can, doesn't mean you should." - I think that applies perfectly here. I mean, we actually used to use things like <font color="red">Red</font> and we moved away from it because it made more sense to group styles in a single Global Attribute. There's nothing stopping you, but I think it's asking for more trouble than it's worth to drop classes for arbitrary parameter names, not to mention if you have an issue and post your code for help, the first response will always be "Why are you doing that, what preprocessor are you using?"
I think it's just the functional probl, if you want to give style u should use class, but if you want to modify u can use query selector cause it will not added an inline style on your html and you can minify the script.
I'm working on WCAG compliance and I need to fix "Empty link" errors.
This is an example of one of the elements providing the error:
<a style="bottom: 0px; left: 7px; width: 25px; cursor: default;" class="histogram_bar_link" title="Less than 2,016 (0)" href="#"
onclick="AjaxControlToolkit.SliderRefinementControl.FindAndSetSliderHandlesAndValuesToRange(" ctl00_ctl43_g_453d6d26_9535_440a_ba72_b7b88de22f31_csr5
", 0, 1, this); return false;" activebarid="ctl00_ctl43_g_453d6d26_9535_440a_ba72_b7b88de22f31_csr5_HistogramActiveBar0" disabled="disabled">
<div id="ctl00_ctl43_g_453d6d26_9535_440a_ba72_b7b88de22f31_csr5_HistogramBgBar0" class="histogram_bar_background">
<div id="ctl00_ctl43_g_453d6d26_9535_440a_ba72_b7b88de22f31_csr5_HistogramActiveBar0" class="histogram_bar_active" style="height: 0px; margin-top: 50px;">
</div>
</a>
I need to find this element and other anchor tags which contain no text within so I can fix them through JS
This is not a link. Do not try to fix it client-side, just correct the HTML. Ideally if you update whatever control generates that HTML, then you do not need to rely on client-side script.
1. Choosing the right control
Let's address the first issue, using the right element...
Does the Control Take Me to Another Page? Use an Anchor
If, when clicked, tapped, or activated by keyboard or voice (or insert novel interaction method here), the user is whisked to another URL (including an anchor on the same page), then use <a href="[URL]">. Make sure you use the href attribute and that it has a real URL, not a “#” (otherwise you’re probably relying on JavaScript, which is not at all necessary for a hyperlink). If an href points to just a “#”, then you’re probably doing it wrong. If it points to a named anchor as part of your progressive enhancement efforts, then that’s totally valid.
Does the Control Change Something on the Current Page? Use a Button
If, when activated, the user is not moved from the page (or to an anchor within the page), but instead is presented with a new view (message boxes, changes in layout, etc.), then use a <button>. While you could use an <input type="button">, it’s more likely you’ll get into conflicts with pre-existing styles and subsequent developers (like me).
Does the Control Submit Form Fields? Use a Submit
If, when activated, information the user has entered (either by manually typing or by choosing items on the screen) is being sent back to the server, then use an <input type="submit">. This had better live within a <form>. If you need more styling control or have to embed more than just a simple text string, use a <button type="submit"> instead. I tend to prefer <input type="submit"> as I find it runs into fewer conflicts (both mentally and stylistically) with developers.
Keyboard User Consideration
Think of keyboard users for a moment. A hyperlink can be fired by pressing the enter key. But a true button can be fired by pressing the enter key or the space bar. When a hyperlink has focus and the user presses the space bar, the page will scroll one screenful. If there isn’t more to scroll then the user just experiences nothing. Given a set of interface elements that look the same, if some work with a space bar and some don’t, you can’t expect users to have much confidence in how the page behaves.
I have a CodePen demo that shows this in action: http://s.codepen.io/aardrian/debug/PZQJyd
I think it’s also worth mentioning that events triggered by a space bar only fire when the key is released, whereas using the Enter key will fire the event as soon as you press the key down (prior to releasing it).
For reference: http://adrianroselli.com/2016/01/links-buttons-submits-and-divs-oh-hell.html
2. Giving it an accessible name
Now let's talk about how you get an accessible name into that button. I assume you do not want it to be seen visually. In that case, give it a class of visually-hidden and apply these styles:
.visually-hidden {
position: absolute !important;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
clip: rect(1px, 1px, 1px, 1px);
padding:0 !important;
border:0 !important;
height: 1px !important;
width: 1px !important;
overflow: hidden;
}
This will allow it to be read by screen readers. It also means you can (and should) dump that title attribute.
3. Combine it
Now take your control and adjust it accordingly:
<button style="…" class="histogram_bar_link" onclick="…" disabled="disabled">
<span class="visually-hidden">Less than 2,016 (0)</span>
<div id="…" class="histogram_bar_background">
<div id="…" class="histogram_bar_active" style="…"></div>
</div>
</button>
I have turned it into a <button> and given it an accessible name by inserting a <span> with the visually-hidden class to hide it from view.
I've two radio buttons with Drop down and I need to put the drop down
in parallel to the second radio button,when we add to the css code
the following its working but this is not a good solution since if I've
bigger page with other control this can override them either
#__box0 {
margin-top: 20px;
margin-left: 20px;
}
there is another option to do that with CSS?
http://jsbin.com/ziziqeyopu/edit?css,js,output
The Html is renders in the renderer method
This is SAPUI5
http://openui5.org/
code but for the question its not relevant since
renderer is related to pure html/css...
i've tried with the following which doesnt works.
.mylist-content>div:first-child {
margin-right:30px
margin-top:50px
}
.mylist-radiolist>DIV:last-child {
margin-left: 30px;
margin-top:100px;
}
If you still haven't figured it out, give this a try:
.mylist-content #__box0 {
position: relative;
top: 20px;
left: 20px;
}
What you see above should do the same thing as your first attempt, but not interfere with anything else on your page, by:
Adding extra application restrictions to the CSS rule, by having the .mylist-content scope restriction (even though this should not be necessary, in theory, because #__box0 is an ID and should be unique on the page).
Shifting the position of the dropdown without affecting any other elements - this is done with position: relative and the corresponding top and left offsets.
Without knowledge of SAP UI and/or your particular situation, I doubt someone will be able to give you a more appropriate answer.
I find it hard to get myself started in this topic so I can write my own widgets for my own needs. How can I combine plain text and HTML elements (links, images), like seen everywhere on the web (Google, Facebook, etc), in a HTML textbox in a way that it still behaves all together like simple text (i. e. deleteable with backspace)?
How does this work? What is the underlying "trick"?
Ok, your question indicates that you need a starting point,
lets then start with a basic HTML such as a div, a ul, and an input
<div class="myTags">
<ul id="tags">
<li class="nd"><input type="text" id="tagInput" placeholder="add some tags..."/></li>
</ul>
</div>
now lets write some jquery to handle the tagging:
$('#tagInput').keypress(function(e){
if (e.keyCode === 13) {
tag = $(this).val();
if(tag.length > 0){
var newLi = $('<li></li>').text(tag);
}
$('#tags').append(newLi);
$(this).val('');
}
});
this jquery snippet listens to the keypress event on the provided input which I called tagInput
the enter key goes with keyCode 13 hence, if it is been hit you take the value of the textbox and and create a new li element then you go and append it to your ul.
what is missing here is how to make the ul looks like horizontal, this is a starting css to be used:
#tags{
float: left;
min-height: 10px;
min-width: 100px;
margin:0px;
padding: 0px;
list-style-type: none;
text-align: center;
background-color: #fff;
border: 1px solid #ccc;
}
#tags li { display: inline-block; padding: 10px;}
#tagInput{background: none;
border: none;}
which will make the ul horizontal, and it will delete the background from the input and adds the border and the background to the ul, which is a lovely trick specially with the placeholder being available, Now for the backspace deleting process it is simple too, take the previous jquery snippet and add the following code to it:
$('#tagInput').keyup(function(e){
if(e.keyCode === 8 && $(this).val().length<=0){
$('#tags li:last').not('.nd').remove();
}
});
which what it does is simply check for keyCode 8 which is a backspace, Note: some people would recommend to listen to keyCode 46 which is delete, it is up to you.
and I also check for the input value so it should be empty to delete the last inserted tag.
Now by wrapping it up you have the following Fiddle to check.
which is a good start point so you can now do whatever you want with the tag styles and many other fancy stuff.
Hope that I helped.
Disclaimer: the previous code is not to be copy pasted, and it is there just for point clarification.
Update
also, adding outline:0 to the input will make more real, see Fiddle
#tagInput{background: none;
border: none; outline:0}
This is all done through javascript (mostly). Look into jquery. All the heavy lifting is done and provides you with a "easy-to-use" javascript library for client-side scripting that can make all these things possible. Obliviously the more complicated you get, the more custom scripting will be needed.
If I understand you correctly, you want to display both text and any other content (images) in one editable component (text area) that looks like native component. I think you can easily achieve that with CSS. The whole trick is to clear the default styling of textarea and wrap it with <div> with custom CSS.
See an example here
You can further enhcance the solution with Javascript and CSS. For instance, you can make the textarea to auto expand as you type
Hope that helps!