Summernote set text through passed parameter in laravel - javascript

My laravel controller passes parameters to the view which I can access by $note in {{ }}. All right, it works. I can get note's title. However, when I want to set the HTML for summernote, it somehow doesn't work. This is what I tried:
<script type="text/javascript">
$('#editor').summernote('code', '{{ $note->html }}');
as well as unescaped using {!! $note->html !!}}. The result is a summernote editor which looks like a normal text input. However, when manually setting [...]('code', '<html><h1>some html for example</h1></html>)[...] it works like a charm.
It is obvious that it's related to the way blade is putting out data using {{ }} but I can't currently figure out why. Using unescaped html had been the first approach that popped up in my mind.

When outputting PHP data for JavaScript to use, I like to use json_encode on the variable. This guarantees variables get output in a JavaScript-friendly version - it'll wrap strings in ' marks, leave integers alone, and output complex arrays/objects as proper JSON.
$('#editor').summernote('code', {!! json_encode($note->html) !!});

Related

Passing php array to javascript function from external php file

I'm working on autofilling an html form based on data from a sqlite database.
I'm using a modified version of the code from this site and in its basic feature it works as expected.
The main input element calls, "onkeyup", a javascript function called "lookup", that in turn calls a external php script passing the current string to query the database.
The script returns a string to update the input form:
echo '<li onClick="fill(\''.$result->value.'\');">'.$result->value.'</li>';
The javascript function "fill" is as follows:
function fill(thisValue) {
$('#inputString').val(thisValue);
setTimeout("$('#suggestions').hide();", 200);
"#inputstring" is simply an input element.
What I would like to do instead of returning a string is to return an array and parse it inside the "fill" function to assign the different values to different elements in html.
The problem is that to pass the php array to javascript I have to convert it somehow. I've tried to make it a json string as suggested many times here on stack, but for what I suppose is a problem of quotes, it always return a null value.
I've tried:
$valuetopass = json_encode($query_result);
whithout
echo '<li onClick="fill('.$valuetopass.');">'.$query_result['text'].'</li>';
and with quotes
echo ''.$query_result['text'].'';
And both fail.
I'm aware that similar question have been already asked 1, 2,ecc... But all of the answers suggest to embed php when assigning the javascript variable. In my case the php is called from the function "lookup" and from that php script I want to return to the function "fill".
How can I produce from inside php a string that includes a json string with a format that can be passed to the "fill" function?
Or alternatively how can I rework the problem so that I don't need to do it at all?
Your JSON string is likely to contain ", so of course you get a syntax problem when you insert that into onClick="fill(...);" untreated.
Using PHP’s htmlspecialchars should be able to fix this in this instance.
In the long term, you might want to look more into the separation of code and data though.
Attaching event handlers using inline HTML attributes is kinda “old-school”, today that should rather be done from inside the script, using addEventListener resp. whatever wrapper methods a JS framework might provide for that. The JSON data could then for example be put into a custom data attribute, so that the script can read the data from there.

What is the right way to pass data from PHP application to JS?

Let's say i want to open a PHP page and without another request, pass some JSON data directly to the browser, so it will be accessible to my Javascript functions.
I don't know the right way to do it, but what i do currently is something like this :
<textarea id="mydata" style:"display:none">[{code:1,name:'John'},{code:2,name:'Mary'},{code:3,name:'Paul'}]</textarea>
I put the data inside a invisible textarea and now the data inside 'mydata' textarea is accessible by JS doing something like this :
var myData = JSON.parse($('#mydata').val());
Although this works, somehow it does not seem to me the right way to do it... I know i could avoid to 'dirty' the html code by getting the data using Ajax after the page opens, but what i'm trying to do here is avoid more requests, so with only one request, everything will be accessible. Actually in my application i have about 5 textareas like these, so with only 1 request to the server i get all data needed.
Thanks
From PHP's perspective, there is no difference between this:
<textarea id="mydata" style:"display:none">[{code:1,name:'John'},{code:2,name:'Mary'},{code:3,name:'Paul'}]</textarea>
and this:
var myData = [{code:1,name:'John'},{code:2,name:'Mary'},{code:3,name:'Paul'}];
Both of the above take the form of:
[a string][the serialized object][a string]
Whether you're surrounding the values with HTML or with JavaScript, that surrounding decoration is just raw output strings as far as PHP is concerned. So there's no need to add the extra step of outputting the JSON to a form element and then using JavaScript to get the form element's value as a string and parse it back to an object. You can just emit the object itself directly to JavaScript code.

How to read Python list in Javascript [in a Django template]

I'm programming in oTree (which is a Django based environment for social experiments) and I have the following problem. I defined some lists in Python and I'd like to import them and use them in an HTML template. If I print them in HTML I manage to see them without any problem, however, once I need to use them in Javascript, the program fails to read them and the single quotes of the elements of the list are converted in '.
The list is imported like this var filtered_elements = {{ array }};.
I think the problem is exactly here, as JS cannot work with them. Do you have any suggestion on how to do that? I considered using JSON, but since I'm quite new to programming, I cannot understand if it's just a waste of time or there is a simpler way out.
Thanks for your answers!
It sounds like your data is already JSON, otherwise you would be getting single quotes and u prefixes. So the only issue is Django autoescaping; you can disable it with the safe filter:
var filtered_elements = {{ array|safe }};
Your data should be JSON, instead of putting the Python list into the contact directly, put "array": json.dumps(array) in the context dictionary.
The JSON string doesn't need HTML escaping inside a tag, but it does need JS escaping! Otherwise some string may include something like </script><script>absolutely anything goes here... to run arbitrary JavaScript, if the JSON contains user data.
So use |escapejs:
var filtered_elements = {{ array|escapejs}};

More efficient way to interpret data from route in view with Angular over Swig?

I have an array of JSON objects being passed from my Node route into its respective view. For example:
res.render("path/to/view", { data: result, data2: result2 })
where both result and result2 are arrays of JSON objects. In my view, I am using them in an ng-init function like so: ( {{}} designates swig, where I have changed [[]] to designate Angular, so in the below example, we are using swig before using my defined Angular init function)
<div ng-init="init( {{ data|json }} )"> </div>
I should say that the above example works fine, but when "data" becomes a very large dataset, SO much time is spend on the swig part - that is converting it to JSON (again..?). Like I said, the "data" is already in the form of JSON, but when I remove the |json from the swig part above, I get a [$parse:syntax] error, and it give me the above line but evaluated:
<div ng-init="init( [object Object],[object Object] )"> </div>
I have tried variations of using ng-init="init( [[ JSON.parse( {{ data }} ) ]] )" so that I evaluate the output to JSON (even though the output already is..?) but cant get anything to work.
Any ideas? Maybe I have the syntax wrong? I don't understand because the "data" is JSON when I pass it to the view, but I can't pass it directly into my init function without getting that syntax error.
Take whatever you're calling with ng-init out of your view and put it in a controller or service.
There are tons of reasons not to use ng-init, so much so that the Angular team basically recommends you don't use it: https://docs.angularjs.org/api/ng/directive/ngInit
Update
I finally think I see what you're trying to do, and it's called bootstrapping. You can embed data into your view server-side like so:
<script>
angular.module("app").constant("myBootstrap", {{ data.stringified }});
</script>
Where data.stringified is your stringified data. Then in Angular you can inject into any controllers you want as a constant with myBootstrap, same as you would for $rootScope, etc., and the data will be available.
So while I am not entirely sure what was causing it to go so slow, I have found a solution, although 'hack' might more accurately describe it. The problem I was having was with Swig taking ages to template my data before passing it into the init function (which I now know is bad practice; that is, to use ng-init to call a function).
I should note for future readers that I am using Node.js, Swig for templating, and Angular for handling the the MVC side of things.
See the above question to see what my code was like before (slow version). Below is my solution:
Routing side
var rawSQLData = makeSQLCall();
var parsedAsJsonSQLData = parseData(rawSQLData);
var parsedDataAsString = JSON.stringify(parsedAsJsonSQLData);
res.render("path/to/view", { data: parsedDataAsString });
HTML
<div ng-init=" init( {{ data|json }} )"> </div>
Angular Controller
$scope.init = function(data){
$scope.dataInScope = JSON.parse(data);
}
As you can see, the only thing I changed was stringifying the JSON before shooting it to the HTML and then parsing it once it gets to the controller.
The reason I think this works is because I am essentially doing all of the JSON processing in parts other than the templating engine (Swig). I tried using no filter, but Swig defaults to converting the data to JSON which was breaking my HTML. The reason that I want to call this a hack rather than a solution is because we stringify the data, and then use the json filter for Swig, which, according to the documentation:
Return a string representation of an JavaScript object.
If I had to guess, I would say that by using the json filter on a string, Swig decides it has nothing to do as the object is already a string and just passes it along (just what I wanted all along!). It is incredible how much faster it is when Swig doesn't touch the data. The JSON stringify and parse are really quick for the size of data, while Swig was taking up to 40 seconds

Right way to escape JSON data from django template

I want to pass a dictionary from django view to a javascript file. The dictionary is built from a database populated by site users. What's the difference between these 2 methods in terms of security?
var mydata = JSON.parse("{{mydata|escapejs}}");
var mydata = {{ mydata|safe }};
Further, the doc at django says this for escapejs : This does not make the string safe for use in HTML. Could you show me an example of how it's unsafe & how can I make it safe.
For anyone coming across this in 2019, Django now provides a third option with the |json_script template filter. This filter takes care of properly serializing and escaping your Python object for use in HTML.
From the docs, using example data with unsafe characters my_data = {'hello': 'world</script>&'}:
{{ my_data|json_script:"my-data" }}
renders to
<script id="my-data" type="application/json">
{"hello": "world\\u003C/script\\u003E\\u0026amp;"}
</script>
You can then access this data in Javascript via
var value = JSON.parse(document.getElementById('my-data').textContent);
The following dictionary can break your page without proper escaping:
{'x':'</script><b>HELLO</b>'}
Inside tags, you can json.dumps it in your view and then use escapejs to stay safe.
(I believe the explanation means that if you want to show the output of json.dumps in HTML, let's say in a <pre> tag, just make sure it is escaped by not using safe or escapejs.)

Categories