How can I make internationalization changes js file for alert, without passing value through template.
I have 'messages' & messages.es-ES file in conf folder.
Years ago I have similar problem in an older version of play framework (2.2.x), that I had solved by writing a twirl template like this:
#()
#import play.api.Play.current
var myI18n = (function() {
var messages = #Html("{" + Messages.messages.flatMap(_._2).map(mess => s""""${mess._1}":"${mess._2}"""").mkString(", ") + "}")
return {
getMessage: function (key) {
if(messages.hasOwnProperty(key)) {
return messages[key];
}
else return key;
}
};
});
In this way, i build at runtime a js file with my messages library and with a basic function for retrieving.
Then I expose an action who returns this (obiviusly need cache by locale):
public static Result javascriptRoutes() {
response().setContentType("text/javascript");
return ok(views.html.i18n.render());
}
and include in pages:
<script type="text/javascript" src="#controllers.routes.I18nJs.javascriptRoutes()"></script>
Finally, I can retrieve the value of messages key with a sample myI18n().getMessage("my.message.key")
Related
How can I mount a tag that has been pre compiled to a function with riot.js/cli to iife JS version.
What am I doing wrong? By getting an empty html DOM as a result.
<html>
<head>
<script type="riot" src="/riot/tag.js"></script>
<script src="/js/riot.js"></script>
<script>
riot.mount('tag');
</script>
</head>
<body>
<tag></tag>
</body></html>
Maybe there is something more I need to do to mount it like a function style?
Also tried to register() first. that did not seem to help. Maybe I did it wrong?
riot.register('tag');
Did you try riot.inject()? That is meant to be used for on-the fly compiling of riot components, but i think it's the step you are missing.
Check also the docs for more context: https://riot.js.org/compiler/#in-browser-compilation-with-inline-templates
you compiled it already so you don't need this part:
const tagString = document.getElementById('tag').innerHTML
// get the compiled code
const {code} = riot.compileFromString(tagString)
BUT: you still need to get the compiled string that sits in your linked file at /riot/tag.js, so you somehow have to fetch that. If you still want to go with that approach (it's 1/2 year later now =D) i would suggest you change the src attribute to data-src (so it's not loaded automatically by the browser and handle the fetching of the compiled string yourself, something like this:
const el = document.getElementById('tag');
let response = await fetch(el.getAttribute('data-src'), {
method: 'GET'
});
data = await response.text();
response = {
headers: [...response.headers].reduce((acc, header) => {
return {...acc, [header[0]]: header[1]};
}, {}),
status: response.status,
data: data,
};
// create the riot component during runtime,
// response.data holds the compiled component code
riot.inject(response.data, 'tag', './tag.html')
Below is are the functions from riot+compiler for reference, they are relatively simple:
// evaluates a compiled tag within the global context
function evaluate(js, url) {
const node = document.createElement('script')
const root = document.documentElement
// make the source available in the "(no domain)" tab
// of Chrome DevTools, with a .js extension
if (url) node.text = `${js}\n//# sourceURL=${url}.js`
root.appendChild(node)
root.removeChild(node)
}
// cheap module transpilation
function transpile(code) {
return `(function (global){${code}})(this)`.replace('export default', 'return')
}
function inject(code, tagName, url) {
evaluate(`window.${GLOBAL_REGISTRY}['${tagName}'] = ${transpile(code)}`, url)
riot.register(tagName, window[GLOBAL_REGISTRY][tagName])
}
function compileFromString(string, options) {
return compiler.compile(string, options)
}
Building a simple notetaking program where you add notes and they get stored into a JSON file, but whenever I write 2 notes the JSON file is emptied completely. This isn't an issue when I just execute the script using $ node notes.js for testing functions, only when I make calls to it from the npm app.
notes.js
const fs = require("fs");
let rawdata = fs.readFileSync('notedb.json');
let notes = JSON.parse(rawdata);
// takes in note, adds it to database
function addnote(note) {
// format item to prepare for json
var jsonitem = {
"note": note
};
// add item to the end of json file
notes.push(jsonitem);
// write the item
fs.writeFile("notedb.json", JSON.stringify(notes), err => {
if (err) console.log("error");
});
// reload the notes on the website
shownotes();
}
function shownotes() {
// put notes into string
var notestostring;
for (i = 0; i < notes.length; i++) {
notestostring+= notes[i]["note"]
}
// add to document
document.getElementById("note-ul").innerHTML = notestostring;
}
notes.html
<!DOCTYPE html>
<script type="text/javascript" src="notes.js">
<!-- input with script that makes it submit when enter key is hit -->
<input type="text" onkeydown="add(this);" id="note-input">
<script>
function add(ele) {
if (event.keyCode == 13) {
addnote(ele.value);
var form = document.getElementById("note-input");
}
}
</script>
Ill add the first note and it will be added to the JSON file with no problems, then add a second note and the entire file will be empty
(Note: I shortened to code to just include the important elements, ignore syntax mistakes)
Eventually gave up the issue and used a CSV file as storage instead. I think it had something to do with asynchronous writing/parsing but as I'm relatively new to javascript I'm not sure how asynchronous handling works.
I'm using Laravel 5.7 & VueJs 2.5.* ...
I have a table with invoice data in it and a invoice is related to the vendor so i also displayed the vendor name in the table, i'm using search feature it works when i search invoice number, but when i want to search with vendor name, its not working.
i did something like this:
I DID THIS IN SCRIPT
mounted() {
Fire.$on("searching", () => {
let query = this.$parent.search;
axios
.get("api/findVTI?q=" + query)
.then(data => {
this.ticketInvoices = data.data;
})
.catch();
});
I MADE A ROUTE
Route::get('findVTI', 'API\TicketInvoiceController#searchVTI');
IN MY INVOICE CONTROLLER I DID THIS
public function searchVTI()
{
if($search = \Request::get('q')){
$VTI = TicketInvoice::where(function($query) use ($search){
$query->where('ticket_invoice_no','LIKE',"%$search%")
->orWhere('ticket_invoice_grand_total','LIKE',"%$search%")
->orWhere('vendor_company_name','LIKE',"%$search%");
})->paginate(10);
}else{
return TicketInvoice::paginate(10);
}
return $VTI;
}
When i write this line:
->orWhere('vendor_company_name','LIKE',"%$search%"); i got an error in console that, vendor_company_name does not exist in ticket_invoices.
I play around with many thing but didn't succeed...
Image For Better Understanding:
You are trying to get at a lower level, you need to look at vendor.vendor_company_name you are skipping the vendor part.
->orWhere('vendor.vendor_company_name','LIKE',"%$search%");
It isnt working because i write orWhere('vendor_company_name','LIKE',"%$search%"), but vendor is relationship and i need to write instead last orWhere something like:
->orWhereHas('vendor', function($query) use ($search){
$query->where('vendor_company_name', 'LIKE', "%{$search}%");
});
I made a web application using Dancer2. I need to call an external program on an ajax request. The problem is that the request freezes until the program is finished.I tried a few things like using an & in the systemcall and fork, but it didn't work.
Here is the simplified code:
Perl:
package Test::App;
use Dancer2;
our $VERSION = '0.1';
get '/' => sub {
template 'index';
};
get '/startscript' => sub{
my $pid = fork();
$SIG{CHLD} = 'IGNORE';
if($pid == 0) {
`sleep 10`;
exit 0;
}
};
get '/gettest' => sub{
return "test"
};
true;
javascript:
$(document).ready(function() {
jQuery.get('/startscript', getSomething);
});
function getSomething(data){
jQuery.get('/gettest', getSomething);
console.log(data);
}
Old question, but the following has worked well for me - use & to have the shell run the command in the background. This returns control to the route handler immediately, and the command runs away in the background.
Perl:
post '/run-slow-script-in-background' => sub {
my $slow_command = q{/full/path/to/slow/script --arg1 what --arg2 ever &};
system($slow_command);
};
In my app.js I have the following:
angular.module('app').controller('userList',
['appSettings'
,function (/*#type {app.appSettings}*/appSettings) {
appSettings.<<== it shows a list here but nothing from autocomplete.js
In my autocomplete.js I have the following (generated by JavaScript printing out my services and their members):
var app={};
app.appSettings={};
app.appSettings.userFailMessages={};
app.appSettings.userFailMessages.invalidJson
="Invalid request, user sent is not valid json.";
NetBeans refuses to code complete appSettings for me and doesn't seem to know it's defined in autocomplete.js. Maybe I'm getting my js doc wrong but tried a mix of combination of #var, #type and #param without success.
It code completes when I type app.appSettings. and gives me a list from autocomplete.js but I would like to know how I can tell NetBeans that the passed argument to the function is app.appSettings.
Maybe I should have autocomplete contain constructor functions instead of object literals as #type suggests a certain type and not an instance.
This is NetBeans 7.3.1
Was close to the answer, to have NetBeans use type you have to define the type. Then to indicate that the parameters passed to your angular module (or any function) are of a certain type I use the #param jsdoc
The angular module:
angular.module('app').controller('userList'
, ['$scope','appRules','appSettings'
,/**
* #param {app.appRules} appRules
* #param {app.appSettings} appSettings
* */
function ($scope,appRules,appSettings,$timeout) {
//<== here both appRules and appSettings give suggestions
// from autocomplete
autocomplete.js (not included in my html file but just there for code suggest)
/*#typedef {Object} app*/
var app={};
app.appRules={};
app.appRules.userIsInRole=function (user,role){};
app.appRules.general={};
app.appRules.general.isEmpty=function (val){};
app.appRules.general.isEmail=function (val){};
app.appSettings={};
app.appSettings.userFailMessages={};
app.appSettings.userFailMessages.invalidJson
="Invalid request, user sent is not valid json.";
app.appSettings.userFailMessages.noPrivilege
="You do not have the privileges needed to change this user.";
I ran the following code in the console on a page that contains my app to generate autocomplete.js:
var inj;
function allServices(mod, r) {
if (!r) {
r = {};
inj = angular.element(document.querySelector('[data-ng-app]')).injector().get;
}
angular.forEach(angular.module(mod).requires, function(m) {
allServices(m, r)
});
angular.forEach(angular.module(mod)._invokeQueue, function(a) {
try {
r[a[2][0]] = inj(a[2][0]);
} catch (e) {
}
});
return r;
};
var output=[];
function addOutput(names,prop){
if(names.length===1){
output.push('var ');
}
output.push(names.join('.'));
if(typeof prop === 'object'){
output.push('={};\n');
for(thing in prop){
//TODO: no arrays or route paths
if(/[0-9\/\\]/.test(thing)){
continue;
}
names.push(thing);
addOutput(names,prop[thing]);
}
}else{
output.push('=');
output.push(
(typeof prop === 'function')?
prop.toString():
JSON.stringify(prop)
);
output.push(';\n');
}
names.pop();
}
function createOutput(){
allMyServices = allServices('app');
addOutput(['app'],allMyServices);
console.log(output.join(''));
}
createOutput();