g:message with arguments inside Javascript / jQuery not working as expected - javascript

I had an issue where String arguments were being truncated to the first character in our g:message tags (longs/integers seemed to be fine).
Ultimately, I figured out we were not calling g:message syntactically correct from within Javascript so some minor tweaks fixed the issue. Problem is - I don't understand why the former doesn't work.
Can anyone describe what was happening here?
jQuery("#myId").html("<g:message code='domain.message.path' args="${command?.foo?.name}"/>"); //incorrect, only displays first character of message
jQuery("#myId").html("${g.message(code: 'domain.message.path', args: [command?.foo?.name])}"); //correct, displays full string

I assume you're rendering this as part of a .gsp page? Here's the thing. In the first one, you're nesting quotes, essentially leaving the ${} section out of the string. Even Stackoverflow can tell; note how that part is a different color:
jQuery("#myId").html("<g:message code='domain.message.path' args="${command?.foo?.name}"/>");
See how the quote at the end of html( is ended by the quote before ${, leaving the ${command?.foo?.name} block outside the string? If command.foo.name was the string "bob", then when this rendered, you'd get:
jQuery("#myId").html("<g:message code='domain.message.path' args="bob"/>");
You might think this looks right, but javascript will handle this poorly.
If you used single quotes for the internal string, like you do with 'domain.message.path', it should work fine:
jQuery("#myId").html("<g:message code='domain.message.path' args='${command?.foo?.name}'/>");

Related

JavaScript string normalize() does not work in some cases - why?

In my debugger I can see an object is retrieved with a unicode character. e.g.
{
name: "(Other\uff09"
}
If this object is referenced using the var myObj in the debugger I see that
myObj.name.normalize()
returns
"(Other\uff09"
If instead I use
"(Other\uff09".normalize()
it returns
"(Other)"
Why?
I've learnt a little since posting this question. Initially I thought that \uff09 was equivalent to ). It's not, instead it's ), aka Full Width Right Parenthesis.
This essentially means that the opening and closing brackets do not match. e.g. ( is not closed by ). This is causing parsing issues for the NodeMailer AddressParser module I'm using.
To normalize it I'm using
JSON.parse(`"(Other\uff09"`).normalize("NFKC")
which translates the string to (Other) rather than (Other).
Breaking this down
JSON.parse(`"(Other\uff09"`)
where the double quotes is required, produces (Other). i.e. It converts the unicode escape characters into the character they represent.
Then
.normalize("NFKC")
converts that into (Other).
This worked for me in this sample. I still need to see if it scales up.

CL-WHO is always starting with a single quote

My issue is that CL-WHO begins each expression with a single quotation market when it turns the Lisp S-expressions into html output. This is okay most of the time, but it is an issue since I am linking my file to an external javascript file. I am trying to make this project simple, and since none of the javascript developers on my team know Common Lisp, using parenscript is likely out of the equation. Here is an example of my issue and one of the errors in my program:
:onclick "alertUser('id')"
When a particular element is pressed within the html document, this should trigger a JavaScript function called alertUser, and the id of the tag should be passed to the JavaScript function as an argument. But no matter what I do, CL-WHO will convert that string into single quotation marks, so I end up with an invalid expression. Here is what that code converts to:
onclick='alertUser('id')'>
Everything is a single quotation so 'alertUser(' is passed as the first string which is obviously invalid and I receive a syntax area in my developer tools. I thought that I could solve this problem by using the format function with escape characters. This would equate to:
CL-USER> (format t "\"alertUser('id')\"")
"alertUser('id')"
NIL
CL-USER>
But when I try that with CL-WHO:
:onclick (format nil "\"alertUser('id')\"")
That translates to:
onclick='"alertUser('locos-tacos-order')"'>
Which is also invalid html. As you can see, CL-WHO will start with a single quote no matter what. Next I tried the CL-WHO fmt function:
:onclick (fmt "\"alertUser('locos-tacos-order')\"")
When I use the fmt function it gets rid of my :onclick expression entirely when it is converted to html!:
id='id'"alertUser('id')">
Lastly I tried the str function, and got similarly invalid output to my original attempt:
onclick='"alertUser('id')"'
Obviously if I code this in pure html it will look like:
onclick="alertUser('id')">
Which is valid.
My question is simply how do I enable CL-WHO to use double quotation marks in these situations instead of single quotation marks?
#jkiiski was has the correct answer in the comments underneath my question, but I wanted to post the answer so that anyone with a similar issue in the future can resolve the problem. As #jkiiski said, there is a variable called ATTRIBUTE-QUOTE-CHAR in the cl-who package that defaults to #\'. You can simply set that variable to #\" instead in order for the default quotations used to be double quotation marks:
(setf *attribute-quote-char* #\")
After adding that line of code near the top of the file my html defaults to:
onclick="alertUser('id')"
and now the javascript can execute properly. Credit to #jkiiski for a correct answer.

Regular Expression in java to get parameters from javascript methods

Long story short, i would like to get the parameters list from JavaScript methods in Java. It works well if i got any parameters, but if the parameter list is empty it's just not working.
For example
function() { return fn.num(tra.getMaster_id(fg)+1)
My regular expression is:
(?<=\({1}).*?(?=\){1})
The result i get:
tra.getMaster_id(fg
The result i want is the empty space between the ().
If i test it with Here everything is fine, but in java it didn't working yet :(
I would appreciate any ideas!
First of all, you don't need {1} repetition quantifiers, everything is repeated just once by default. Secondly, since regexes in java are just strings that get interpreted, you have to escape escaping slashes (\):
(?<=\\().*?(?=\\))
Thirdly, you are getting the match that you want, it is just that there are more than one matches in this case. You are currently fetching the last one and not the first one.

Is AngularJS parsing the value incorrectly?

I have an extremely simple example here: http://jsfiddle.net/daylight/hqHSr/
To try it, just go to the fiddle and click the [Add Item] button to add some rows.
Next, click the check box next to any item and you'll see something similar to the following:
Problem: Only Displays Numeric Part
The problem is that the value should display the entire string shown in the row. In the example that means it should display: 86884-LLMUL.
Notice that it only displays the numeric part of the value.
If you look at the control you'll see that I'm using an input of type="text".
Also, if you look at the model (simpleItem) object you'll see that the one property it has is a string.
The JavaScript for the model class looks like:
function simpleItem(id) {
this.id = id;
}
My Attempt To Force to String Type
When I generate each of the simpleItems I even go so far as to set them to a character when I call the constructor (just to force the id to be set to a string type).
Here's the code that initializes each of the simpleItem ids:
currentItem.id = getRandom(100000).toString() + "-" + getRandomLetters(5).toUpperCase();
You can see the rest of the code in the fiddle, but the thing is I generate a random value and concatenate the value together with a hyphen and 5 letters. It's just a silly little piece of code for this sample.
But now, here is the part where it gets really odd.
If I simply change the hyphen - to another character like an uppercase X I get an error each time I click on the checkbox.
Here's the changed code and the new output, which you can see at the revised fiddle: fiddle version 2
currentItem.id = getRandom(100000).toString() + "X" + getRandomLetters(5).toUpperCase();
Also, now if you open Dev Tools in your browser you'll see in the console that Angular is now reporting an error each time you click the [Add Item] button. It looks like:
Adding Single-quotes ?Fixes? It
If you go up to the HTML and alter the following line from this:
ng-init="itemId ={{l.id.toString()}}"
to this
ng-init="itemId ='{{l.id.toString()}}'"
Now when you run it, the error will go away and it will work as you can see at the updated fiddle here: fiddle Version 3
Angular : Converts Hyphen to Minus Sign?
You see, Angular seems to be converting it to a numeric, attempting to do math on it (parsing the hyphen as a minus sign) and then truncating the string portion. That all seems to work when I use a hyphen, but when I use a X then Angular chokes.
Here's what it looks like when you add the single-quotes - of course the angular errors in Dev Tools console go away too.
Angular Forces to Numeric Type?
Why would this occur in Angular? It's as if it is attempting to force my string value to a numeric even though the INPUT element is type text and the JavaScript var is type string.
Anyone have ideas about this?
What About the Asterisk (multiplication symbol)?
Right as I was completing this I wondered what would happen if I changed the - to a * and ran it again. This time I saw the error below, which is indicative that something is attempting to convert to numeric.
This is the expected behavior. Angular is merely interpolating the text you have in your scope into the ng-init expression using scope.$eval and then executing that expression. This has very little to do with what is the type of the input box of the rest of the surrounding context.
It is definitely not desirable that Angular should wrap any interpolation it does in quotes, it'll break its use in all other places such as class="my-class {{dynamic-class}}".
Replace your ng-init with
ng-init="itemId =l.id.toString()"
In following with the docs, you should only use init in special circumstances anyway, you should rely on your controller for this. http://docs.angularjs.org/api/ng.directive:ngInit
I think we're just getting confused with Angular's weirdness. Basically, you're giving angular a string which it's turning into a javascript expression because it's in a {{}}. It's already, explicitly, a string (between the double-quotes):
ng-init="itemId ={{l.id.toString()}}"
It's apparently ignoring the fact that you're saying "hey, no really, this is a real string" with your l.id.toString(). It doesn't care. It's already a string and is going to evaluate it.
Just use the single quotes?
If you ng-init itemId={{undefined===undefined}}, what would you expect to happen? (it prints "true" in the alert).
Same with this: (undefined === undefined is in quotes) ng-init itemId={{'undefined===undefined'}}; prints true in the alert.
ng-init expects an angular expression. You don't have to use curly brackets there. You can simply write it like this:
ng-init="itemId=l.id" ng-click="checkBoxClicked(itemId)"

REGEXP based string.prototype.split insertion glitch

I was working on a parser that could read HTML however the code that splits it causes "l"s to be inserted in every other entry of the produced array.
The regexp is this:
textarea.value.split(/(?=<(.|\n)+>)/)
What it's supposed to do is split entry/exit/single HTML/XML tags while ignoring tabs and line terminators (it just appends them to tags they were split with)
May I have some insite as to what's happening?
You can view code in action and edit here:
http://jsfiddle.net/termtm/ew7Mt/2/
Just look in console for result it produces.
EDIT: MaxArt is right the l in last <html> causes the anomalies to be "l"s
Try this:
textarea.value.split(/(?=<[^>]+>)/);
But... what Alnitak said. A fully-fledged HTML parser based on regexps, expecially with the poor feature support of regexps in Javascript, would be a terrible (and slow) mess.
I still have to find out the reason of the odd behaviour you found. Notice that "l" (ell) is the last letter of "<html>", i.e., the first tag of your HTML code. Change it to something else and you'll notice the letters change.

Categories

Resources