I'm using $.cookie() to pull all the values from a cookie, in JSON format:
var props = $.cookie('params');
props returns:
{"distinct_id": "13f97d6600b42e-000e6293c-6b1b2e75-232800-13f97d6600cc82","utm_source": "the_source","utm_term": "myterms","utm_campaign": "campaign","utm_medium": "medium","utm_content": "content"}
I'm inserting this dynamically into a form with jQuery, and I want to ensure everything is going to POST properly, even though there's all kinds of crazy characters that could be in there which would normally conflict with HTML (fully qualified urls, &, ", ', maybe even a > or <)
I also need to make certain it works in IE6, IE7, etc.
var input = $('<input type="hidden" name="CustomField1">');
input.appendTo($('form[data-params=track]')).val(props);
It would *appear* to be working, but I want to make 100% sure I'm doing this right as it's quite important there are no bugs for this step.
I am pretty sure val() does not need any additional escaping as you are not actually editing raw HTML. val() sets DOM value on an element.
Generally setting attributes or properties through DOM/jQuery should be fine. Those will be auto-escaped when rendering innerHtml. But if you submit a page it does not even have to render anything -- it can just directly copy values from DOM to request.
Since your are setting the value of an input field, it should just work fine, there is no need to escape/process any characters in the input's value.
You can use the JavaScript escape() function to make sure the string get's escaped properly for display in the browser.
Related
I've been going through and trying to find an answer to this question that fits my need but either I'm too noob to make other use cases work, or their not specific enough for my case.
Basically I want to use javascript/jQuery to replace any and all ampersands (&) on a web page that may occur in a links href with just the word "and". I've tried a couple different versions of this with no luck
var link = $("a").attr('href');
link.replace(/&/g, "and");
Thank you
Your current code replaces the text of the element within the jQuery object, but does not update the element(s) in the DOM.
You can instead achieve what you need by providing a function to attr() which will be executed against all elements in the matched set. Try this:
$("a").attr('href', function(i, value) {
return value.replace(/&/g, "and");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
link
link
Sometimes when replacing &, I've found that even though I replaced &, I still have amp;. There is a fix to this:
var newUrl = "#Model.UrlToRedirect".replace(/&/gi, '%').replace(/%amp;/gi, '&');
With this solution you replace & twice and it will work. In my particular problem in an MVC app, window.location.href = #Model.UrlToRedirect, the url was already partially encoded and had a query string. I tried encoding/decoding, using Uri as the C# class, escape(), everything before coming up with this solution. The problem with using my above logic is other things could blow up the query string later. One solution is to put a hidden field or input on the form like this:
<input type="hidden" value="#Model.UrlToRedirect" id="url-redirect" />
then in your javascript:
window.location.href = document.getElementById("url-redirect").value;
in this way, javascript won't take the c# string and change it.
I would like to ask a question regarding a strange behavior I face using the escape Ascii characters for some Swedish chars.
More specifically, in order to support a multilingual site, I have a json file where I have specified all required messages in Swedish, i.e. 'Avancerad sök'.
Then when the page loads the first time, I set this value to an input text and it is displayed properly: 'Avancerad sök'. But when I click a button and set again the value of this input text I get: 'Avancerad sök'.
Does anyone have faced a similar problem?
Thanks a lot!
Code:
q('#keyword').val(qLanguage.qAdvancedHint);
I execute this code both times. qLanguage is an object which I fill it from the json file and qAdvancedHint a specific key.
Don't know have the specific encoding is called. But tested with js's unescape method, but didn't work.
However a solution, a bad/ugly one, could be to ask jQuery to parse it for you then add it as a value property:
var text = $("<span/>").html(qLanguage.qAdvancedHint).text();
q('#keyword').val(text);
I'm using document.location.hash to preserve state on the page, and I'm putting url-encoded key value pairs up there, separated by "&" chars. So far so good.
However I'm running into an annoying problem on Firefox -- Firefox will quietly url-decode the hash value on the way in, so when you get it out later it's been decoded.
I can patch the problem by detecting when I'm running on firefox and calling encodeURIComponent on everything twice on the way in, but obviously that is hideous and I don't really want to do that.
Here's a simple example, where I encode "=" as "%3D", put it in the hash, and when I get it out later it's been turned back into "=" automatically:
// on the way in::
document.location.hash = "foo=" + encodeURIComponent("noisy=input");
//then later.....
// on the way out:
var hash = document.location.hash;
kvPair = hash.split("=");
if (kvPair.length==2) {
console.log("that is correct.")
} else if (kvPair.length==3) {
console.log("oh hai firefox, this is incorrect")
}
I have my fingers crossed that there's maybe some hidden DOM element that firefox creates that represents the actual (un-decoded) hash value?
but bottom line -- has anyone run into this and found a better solution than just doing browser detection and calling encodeURIComponent twice on Firefox?
NOTE: several other questions I think have the same root cause. Most notably this one:
https://stackoverflow.com/questions/4834609/malformed-uri-in-firefox-not-ie-using-encodeuricomponenet-and-setting-hash
I would strongly advise against using the hash value to preserve the state. Hash is supposed to point to object's fragment-id, as explained in RFC 1630
This represents a part of, fragment of, or a sub-function within, an
object. (...) The fragment-id follows the URL of the whole object from which it is
separated by a hash sign (#).
Is there anything stopping you from using cookies to preserve the state? Cookies are simple enough to use in JS, described on Geko DOM Reference pages, and would do the trick quietly, without appending values to the URL which is never pretty.
If you absolutely have to use hash though, you may want to consider replacing '=' with some other character, e.g. ":".
What you could do, is change the "=" to something else using
var string = string2.replace("=", "[$equals]")
You may have to run the line above a couple of times, depending on how many "=" there are.
Then same process you had as above.
NB If you require it for further code, you can replace [$equals] back to "=" after splitting the hash into an array.
html
<div contentEditable="true">testing....</div>
jQuery
$(document).ready(function(){
$('[contenteditable]').removeAttr('contenteditable');
});
above codes is fine and working. you can feel it here.
Now, try this
$('[contentEditable]').removeAttr('contentEditable');
// notice the CamelCase of the string contentEditable
in FF 3.6, it gives an error on the console
An invalid or illegal string was
specified" code: "12 elem[ name ]
= value;
and the div is still editable.
I suspected it was the jQuery selector, but is not. By further inspection, it was the argument passed on the .removeAttr('contentEditable');. It works when all small letters. So, I thought it should be all small letters. I'm curious so I tried adding CLass as an attribute and do .removeAttr('CLass');. But then it works without error.
So, how come contentEditable is giving me that error?
update
from Kobi, it seems that it actually accept any case except, contentEditable (I did try too).
CamelCase
This isn't about small letters, but about the exact casing. Any other casing than contentEditable works, for example: removeAttr('ConTentEditable');.
I can't find the exact source of the problem, I guess it's a Firefox restriction.
It seems jQuery sets the attribute to an empty string before removing it, which is what's causing the error. This seems to work better:
$('[contentEditable]').attr('contentEditable', false);
You could call it a bug, but really the framework is designed this way. removeAttr, along with other attr functions, points to jQuery.attr() to set the attribute's value. After setting the attribute to "", it then attempts to remove it. The code for attr() specifically checks to see if the given string is a property name on the object first using the in operator:
// If applicable, access the attribute via the DOM 0 way
if ( name in elem && notxml && !special ) {
(from jQuery 1.4, line 1452-1453)
Since you're supplying the camelCase property name, it uses that instead of elem.setAttribute(), which is specifically the cause of the problem. For any other case, name in elem would return false (because property names are case sensitive), which is why it's successful then. jQuery does this mostly to work around cross browser issues with setAttribute().
It looks like Firefox has a problem with setting the property to an empty string, unless you have the same problem in other browsers. You could try and file a bug either on the jQuery site or MDC.
contentEditable seams to be a special attribute:
http://www.whatwg.org/specs/web-apps/current-work/multipage/editing.html#contenteditable
The contentEditable property (not attribute, since that isn't what attr() and friends usually deal with) expects a string value, one of "true", "false" and "inherit". I wouldn't use jQuery to turn off contentEditable, but I imagine the following would work:
$('[contenteditable]').attr("contentEditable", "false");
Or you could bypass jQuery for setting the actual contentEditable property:
$('[contenteditable]').each(function() {
this.contentEditable = "false";
});
I have a generic function that returns URLs. (It's a plugin function that returns URLs to resources [images, stylesheets] within a plugin).
I use GET parameters in those URLs.
If I want to use these URLs within a HTML page, to pass W3C validation, I need to mask ampersands as &
/plugin.php?plugin=xyz&resource=stylesheet&....
but, if I want to use the URL as the "url" parameter for a AJAX call, the ampersand is not interpreted correctly, screwing up my calls.
Can I do something get & work in AJAX calls?
I would very much like to avoid adding parameters to th URL generating function (intendedUse="ajax" or whatever) or manipulating the URL in Javascript, as this plugin model will be re-used many times (and possibly by many people) and I want it as simple as possible.
It seems to me that you're running into the problem of having one piece of your application cross multiple layers. In this case it's the plugin.
A URL as specified by RFC 1738 states that a URL should use a & token to separate key/value pairs from one another. However ampersand is a reserved token in HTML and therefore should be escaped into &. Since escaping the ampersands is an artifact of HTML, your plugin should probably not be escaping them directly. Instead you should have a function or something that escapes a canonical URL so that it can be embedded in HTML markup.
The only place that this is likely to actually happen is if you are:
Using XHTML
Serving it as text/html
Using inline <script>
This is not a happy combination, and the solution is in the spec.
Use external scripts if your script
uses < or & or ]]> or --.
The XHTML media types note includes the same advice, but also provides a workaround if you choose to ignore it.
Try returning JSON instead of just a string, that way your Javascript can read the URL value as an object, and you shouldn't have that issue. Other than that, try simply HTML decoding the string, using something like:
function escapeHTML (str)
{
var div = document.createElement('div');
var text = document.createTextNode(str);
div.appendChild(text);
return div.innerHTML;
};
Obviously you'll want to make sure you remove any reference to DOM elements you might create (which I've not done here to simplify the example).
I use this technique in the AJAX sites I create at my work and have used it many times to solve this problem.
When you have markup of the form:
<a href="?a=1&b=2">
Then the value of the href attribute is ?a=1&b=2. The & is only an escape sequence in HTML/XML and doesn't affect the value of the attribute. This is similar to:
<a href="<>">
Where the value of the attribute is <>.
If, instead, you have code of the form:
<script>
var s = "?a=1&b=2";
</script>
Then you can use a JavaScript function:
<script>
var amp = String.fromCharCode(38);
var s = "?a=1"+amp+"b=2";
</script>
This allows code that would otherwise only be valid HTML or only valid XHTML to be valid in both. (See Dorwald's comments for more info.)