Using Regex to validate user input as CSS? - javascript

I am writing a program that allows the user to create a page using a drag-n-drop GUI. Every element (image, text, etc) will have easy-to-use CSS selectors like background-color and font-size, however my client has asked for the ability, when necessary, to add custom CSS to the element as a final option.
Looking past the dangers of users possibly typing in and saving valid javascript functions, trying to style the body tag etc. (I will make sure to handle that by escaping/PDO-handling user input in PHP), how can I write a regex (or another functionality) that tests, crudely, if what the user types in is valid CSS. My regex at the moment is this:
([A-Za-z\-]+?:\s*?[A-Za-z\-]+?;)+?;
And I run it using
var reg = /([A-Za-z\-]+?:\s*?[A-Za-z\-]+?;)+?/;
if (reg.test(textarea.val())) {
console.log("yay");
//add CSS to element
} else {
console.log("nay");
//let user know their input is wrong
}
This works fine to validate
css-selector: css-value;
However, anything after that it will still validate as true because the first part will be true:
css-selector: css-value;
invalid-css is here!
As for what I mean with crudely, all that I find necessary to check is the presence of a : and a ; with text, and possibly a - in-between, it is not necessary to check if the css-selector itself actually exists as a CSS attribute nor if the CSS-value is a valid value of said selector.
Is there a way to ensure the entire input value MUST be true?
As a final note, if you see a potential danger not directly related to inserting script-tags or styling potential whole-page elements that I should be vary of, please let me know
Edit: due to many saying that I can't validate real CSS, I am going to specify my requirement a bit further; first, valid regex:
css-selector: css-value;
other-css-selector: other-css-value;
invalid regex:
css-selector: css-value;
invalid-css is here!
Secondly, what I want is something that validates if I can pass the string to:
$(element).css(validated-string);
And have chrome handle whether what is applied is actually valid, much like it does if you edit CSS live
Secondly, I mention PHP validation, but what I want is to update the CSS live so the user can see the effect of their edits as they add them

As regex you can use ^([A-Za-z\-]+?:\s*?[0-9A-Za-z\-%]+?;\s*?)*?$, but still i'm not quite sure that it will discard all the invalid css.
If you have test: 100something; is valid for the regex but is not valid CSS.

Related

Remove last 3 letters of div (hidde also in browser page source)

this is my HTML
<div id="remove">Username</div>
and this is my JS code
function slice() {
var t = document.getElementById("remove");
t.textContent = t.textContent.slice(0, -3);
}
slice();
Username load from foreach
{foreach from=$last_user item=s}
{$s.date}
{$s.username}
{/foreach}
This code working and remove 3 letter but when right click on browser and look at page sources i can see "Username" !
I need remove three letter because of privacy and security .
something like
*** name or usern ***
Thank for help me !
The only secure way to make sure the client can't see a particular piece of information is to never send it to the client in the first place. Otherwise, there will always be a way for the client to examine the raw payloads of the network requests and figure out the information they aren't supposed to know.
You'll need to fix this on your backend - either hard-code in
<div id="remove">Usern</div>
or, for a more dynamic approach, use a template engine (or whatever's generating the HTML) and look up how to change strings with it. For example, in EJS, if user is an object with a username property, you could do
<div id="remove"><%= user.username.slice(0, -3) %></div>
Changing the content only with client-side JavaScript will not be sufficient, if you wish to keep some things truly private.
With Smarty, you can define a modifier that takes a string and returns all but the last three characters of it.
function smarty_modifier_truncate_three($string)
{
return substr($string, 0, -3);
}
and then in your template, replace
{$s.username}
with
{$s.username|truncate_three}
If you want only the first three characters, it's easier because you can use the built-in truncate.
{$s.username|truncate:3}
JS doesn't change the source, it can only change the DOM, so what you can do is to keep the element empty and add a value to it using js, but don't forget that js runs on the client's side so its better here to send the string from the server without the last 3 characters.

How to apply CSS to part of some text without breaking the text content itself

I am currently considering how to support a legacy web application in a new language(language here meaning spoken language - not code!).
I will be doing this using some form of javascript internationalisation library however I've stumbled upon an issue.
Currently the application can be driven solely by keyboard shortcuts - these short cuts are indicated to the user by underlining the letter of a function label on the screen which corresponds with a short cut.
For example:
<u>R</u>un
<u>J</u>ump
J<u>o</u>g
The problem is when these strings are replaced with tokens for internationalisation the strings are going to be stored as plain text and I would like to not have to tarnish these strings files with html tags(especially a tag which is discouraged nowadays anyway)
If we decouple logic to decide which letter to underline - which could well change with along with a language change - how could I go about underlining a single character in a string? Is it even possible?
//HTML
//Strings file
action.jump=Jump
//Javascript/JQuery
$('<someHowOnlySelectAParticularLetter('J')> #jump').css({text-decoration:overline});
function someHowOnlySelectAParticularLetter(var character){
//TODO
}
Thanks in advance for any responses - even I haven't explained the issue at hand clearly please say so and I will attempt to clarify any questions!
What letter is "active" is language-dependent, so this info has to be stored in each language specific config file (translation table file):
English:
RUN: "Run"
RUN_ACTION: "R"
French:
RUN: "Courir"
RUN_ACTION: "C"
Then use this information (and meta-infromation) to generate your HTML:
function buildAction(label, letter) {
return label.replace(letter, '<u id="action-' + letter + '">' + letter + '</u>');
}
var html = '<p>menu: ' + buildAction(RUN, RUN_ACTION) + ', ...</p>';
document.write(html);
Then you can $('#action-' + RUN_ACTION).css and $('#action-' + RUN_ACTION).click.
With this you only need to switch between translation table files.
I'd generate the HTML server-side though.
If you want to keep using that design, you're gonna run into all sorts of problems.
What if the translated word doesn't have the letter shortcut you applied to your other language?
If a user gets used to a set of shortcuts and changes the language, are all the shortcuts he is used to going to change?
For example, Ctrl+S is a widely used shortcut for Save, even if some languages don't have a S in their translation of 'Save'. Change that letter to W, which is the common shortcut for Quit, and you're in for an unpleasant user experience.
I suggest you change your markup to
(R) Run
(J) Jump
(O) Jog
That way you only need to translate the word part, and leave the shortcut as it is.
It seems that you would have to use a little bit of RegEx (regular expressions) and .split to be able to grab that letter, store it in a variable and then style it with jquery's .css method.
It is an admirable goal to separate data from presentation.
I don't think pure CSS will get you all the way there, without also having some supporting HTML markup.
You actually need the hotkey information in two places:
In the UI markup
In the code that processes key presses
I would suggest that you store the information about the hotkey in a format similar to:
// Word Hotkey Offset Function Language
// Sichern S 0 Save DE
// Springe p 1 Jump DE
(example above uses German).
Use that data to drive
Rendering of the UI (e.g. when rendering to HTML markup, wrap the character position designated by Offset with a tag of your choice that matches your CSS rules.
Have the code that captures key clicks and executes functionality use the same data.

jQuery validation, NOT the normal plugin

I've been looking at the jQuery Validation Plugin and it seems like overkill (my site's script requirements are ballooning), and also not quite what I want.
Let me define some terminology: an <input type="text"> field's status is VALID if it matches both RegEx 1 and RegEx 2, PARTIAL if it matches RegEx 1 but not RegEx 2, and INVALID if it doesn't match RegEx 1.
For example, RegEx 1 could be /^[A-Z_]*$/ and RegEx 2 could be /^[A-Z]+(_[A-Z]+)*$/.
The requirements are:
any key press which would lead to an INVALID status is ignored, without interfering with focus or the caret position, and without the value ever being seen to change,
otherwise the status is updated after every key press to be either VALID or PARTIAL, and
whenever an input's status changes, a callback is invoked.
Seems pretty straightforward. This is basically the QStringValidator model.
I have jQuery core but I'm new to it. How can I implement this? Thanks.
P.S. if the best solution lies outside of jQuery, IE support is not required.
if (this.value.match(this.getAttribute('data-regex1')) {
if (this.value.match(this.getAttribute('data-regex2')) {
do_whatever_for_full();
} else {
do_whatever_for_partial();
}
} else {
do_whatever_for_invalid();
}
Put your regexes into the element as custom attributes (data-regex1, data-regex2) then check the data as it changes (not sure how many events you want to check but you probably have to check with onkeydown ignoring enter and tab, or you could create a timer onfocus and just check every half second or so).

Change an input when you change another one in javascript

Hard to define the title ^^
I want to have to input fields. For example: one where you type in a color (string) and another for the code of the color (varchar).
Like this: |Green| |#657EC9| (just random color-code)
I do not want to learn how to find the color-code but how to match a value or variable with another. It was just an example.
What i wanna know is how I in the best way auto generate one of the fields when I fill in the second. When I type 'green' in the first field I want the code to automatically appear in the second and vice versa. I just want to do it for a few colors.
I am very new to PHP, HTML and Javascript and could need some good advice about how I should handle the problem.
Thank you
I would tend to just map values to an object literal, so:
var colors = {
Green:'#657EC9',
Red:'#00ffff'
}
Now you could get your value with colors[fieldInputVal] where fieldInputVal might be 'Green' or 'Red' although of course you'd have to test if there actually was a property there. Object literals are the main reason I rarely find a use for switch statements in JS.
As for the event JS, I'm going to be lazy and go with JQuery rather than explain attachEvent vs. addEventListener which would be necessary if you're supporting IE8 or below. If you want to normalize for that yourself and skip JQuery, look up 'addEvent contest' on quirksmode.org
$('.input_one').change( function(){
//note: only fires after the field loses focus - you tab out or focus another field
var inputVal = $(this).val();
if(colors[inputVal] !== undefined){
$('.input_two').val(colors[inputVal]);
}
} );
note: I did not test this code for syntax goofs.
If you want to be more flexible and accept 'green' or 'Green', I would just capitalize the first character before you use it for the lookup. To do the lookup on every character add, you'd have to look up the keyup or keydown events (I prefer keyup to avoid breaking the browsers back when somebody holds a key down).

How should I associate server-side data with client-side UI elements in HTML?

I run into this problem constantly while developing AJAX applications. Let's say I want users to be able to click on a "flag" icon associated with each comment on my site, which results in an AJAX request being sent to the server, requesting that the comment be flagged. I need to associate a comment id with the comment on the client side so that the AJAX request may communicate to the server which comment to flag.
This page explains a number of ways to annotate HTML in this manner, but none of them are very satisfactory. While I could just use an id or class attribute to associate the comment id with the flag button (e.g. id="comment_1998221"), this fails with more complex data that doesn't fit well into those attributes (e.g. arbitrary strings). Is there a best practice for this sort of thing? Every time I need to do this, I end up with some kludge like using the id attribute, a hidden form field, or worse yet a span set to display:none.
The HTML5 data-* attributes seem like a perfect solution, but I've seen a lot of animosity toward them, which makes me think that people must already have a solution they're happy with. I'd love to know what it is.
This page explains a number of ways to annotate HTML in this manner, but none of them are very satisfactory.
Still, they are pretty much all you've got. Although that page isn't a terribly good summary, there are errors and it misunderstands what ‘unobtrusive’ JavaScript means.
For example it is in fact perfectly valid to put a script element inside body — just not directly inside a table element. You could put all the script fragments at the bottom of the table, or put each row in its own table, or even, with some limitations if you are intending to mutate the DOM, inside the row in question.
Setting “id="comment-123"” then scanning for all rows with an id starting with ‘comment-’ is indeed good for your particular case. For setting non-identifying extra info attributes, you could use either HTML5 data-attributes or hack it into the classname using eg. “class="comment type-foo data-bar"”. Of course both IDs and classnames have their limits about what characters you can use, but it's possible to encode any string down to valid strings. For example, you could use a custom URL-style encoding to hide non-alphanumeric characters:
<tr class="greeting-Hello_21_20_E2_98_BA">
...
</tr>
function getClassAttr(el, name) {
var prefix= name+'-';
var classes= el.className.split(' ');
for (var i= classes.length; i-->0;) {
if (classes[i].substring(0, prefix.length)==prefix) {
var value= classes[i].substring(prefix.length);
return decodeURIComponent(value.split('_').join('%'));
}
}
return null;
}
var greeting= getClassAttr(tr, 'greeting'); // "Hello! ☺"
You can even store complex non-string values in this way, by encoding them JavaScript or JSON strings then retrieving them using exec (or JSON.parse where available).
However, if you are putting anything non-trivial in there it soon gets messy. That's where you may prefer comments. You can fit anything in here except the sequence '--', which is easily escaped if it happens to come up in a string.
<table>
<tr class="comment">
<td>...</td>
<!-- {"id": 123, "user": 456} -->
</tr>
</table>
function getLastComment(node) {
var results= [];
for (var i= node.childNodes.length; i-->0;)
if (node.childNodes[i]==8)
return node.childNodes[i];
return null;
}
var user= getLastComment(tr).user;
The summary warns that this may not be guaranteed to work because XML parsers may discard comments, but then DOM Level 3 LS parsers must keep them by default, and every browser and major XML library so far does.
jQuery data API is nice for this.
Suppose you have the following DOM...
<div class="comment">
Flag
Some text
</div>
Then, assuming you are also loading these elements by ajax, you can do
$(".comment").data('someKey', (any javascript value/object));
Then later, upon click handler to the flag, you can do...
$(".flagSelector").click(function(ev) {
var extraData = $(this).closest(".comment").data("someKey");
// use extraData along with your request
});
If you are generating the comments on the server side and shipping them with the initial page, you need to figure out how to initialize the data. One way would be to have unique ID-s for the comment and upon pageload, still load the custom data from the server by Ajax.
Here is how I would do this:
When rendering the page server-side, generate the flag link as a normal link, so that it would work fine if you didn't have javascript enabled.
<a class="flag_link" href="/comment/123/flag/"><img src="flag.gif" /></a>
Then, in the javascript, add a click event to do this by ajax instead. I'll use jQuery for my example, but the same thing is not hard to do without it.
<script>
$('a.flag_link').click(function() {
$.get($(this).attr('href'), function() {
alert('you flagged this comment');
});
});
</script>
Of course, you'll do something more user-friendly than an alert to signal success.

Categories

Resources