I have a page using i18next on node.
In the translation files, there are translations (duh) for various things (it's like a database for little helper snippets)
now i want to build a page, where the user can view them individually.
idea
i want to access the loaded xx-translation.json and make a (dropdown?) menu containing all the entries in one namespace
{
"category": {
"subcategory": { // i want to get ["bla", "blu", "bli"] as result
"bla" : "ble",
"blu" : "blo",
"bli" : "bly"
}
}
}
i'm thinking about a simple loop like
var amountOfEntries = translationJSON.category.subcategory.length;
for (var i = 0; i < amountOfEntries; i++) {
$('#menu'). //append that entry somehow
}
tldr questions
is there a way to access the translation.json inside my "normal" js and count the number of entries?
and
how can i build a menu piece by piece with the entries? (this is bonus, i think i'd manage to do that. the main question is the first one)
thanks
Check out lodash.js for some good collection utility functions. You can iterate over the object with something like:
_.each(subcategory, function(val, key){
$(".menu").append("<li>" + key + ": " + val + "</li>");
});
is that helpful?
UPDATE
After clarifying your question in the comments above, I think what you're looking for is either getResource() or getResourceBundle().
Related
I am attempting to use JSLink ..finally.. and I am having some trouble that I cannot seem to straighten out. For my first venture down the rabbit hole I chose something super simple for use as proof of concept. So I looked up a tutorial and came up with a simple script to draw a box around the Title field of each entry and style the text. I cannot get this to work. Is there any chance you can take a look at this code for me? I used the following tokens in the JSLink box.
~sitecollection/site/folder/folder/file.js
And
~site/folder/folder/file.js
The .js file is stored on the same site as the List View WebPart I am attempting to modify. The list only has the default “Title” column.
(function () {
var overrideContext = {};
overrideContext.Templates = {};
overrideContext.Templates.Item = overrideTemplate;
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideContext);
}) ();
function overrideTemplate(ctx) {
return “<div style=’font-size:40px;border:solid 3px black;margin-bottom:6px;padding:4px;width:200px;’>” + ctx.CurrentItem.Title + “</div>”;
}
It looks as though you are attempting to override the context (ctx) item itself, where you actually just want to override the list field and the list view in which the field is displayed. Make sense?
Firstly, change overrideContext.Templates.Item to overrideContext.Templates.Fields :
(function () {
var overrideContext = {};
overrideContext.Templates = {};
overrideContext.Templates.Fields = {
// Add field and point it to your rendering function
"Title": { "View": overrideTemplate },
};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideContext);
}) ();
Then when the JSLink runs the renderer looks for the Title field in the List view, and applies your overrideTemplate function.
function overrideTemplate(ctx) {
return “<div style=’font-size:40px;border:solid 3px black;margin-bottom:6px;padding:4px;width:200px;’>” + ctx.CurrentItem.Title + “</div>”;
}
In terms of running multiple JSLinks on a SharePoint page, it is quite possible to run multiple JSLink scripts, they just need to be separated by the pipe '|' symbol. I use SharePoint Online a lot and I see the following formatting working all the time (sorry Sascha!).
~site/yourassetfolder/yourfilename.js | ~site/yourassetfolder/anotherfilename.js
You can run as many scripts concurrently as you want, just keep separating them with the pipe. I've seen this on prem also, however you might want to swap out '~sites' for '~sitecollection' and make sure the js files you are accessing are at the top level site in the site collection if you do so!
I have noticed when running multiple JSLinks on a list or page because they are all doing Client Side Rendering, too many will slow your page down. If this happens, you might want to consider combining them into one JSLink script so that the server only has to call one file to return to the client to do all the rendering needed for your list.
Hope this helps.
I am trying to use this conversationThreading-js code to group emails into threads but documentation is scant and/or I am not able to understand it. Has anyone used this bit of code before or used the JWZ email conversation threading algorithm on which it is based?
This is where I am so far:
using Electron I load and parse a local mbox using node-mbox and node-mailparser
I build an array of javascript objects which have key value pairs of messageId, inReplyTo and references.
Using example code from the test file for this lib I try to build the threads but apparently I am not doing it right. I get no errors but I also get no threads (and my test mbox does contain threaded conversations).
Maybe I am misunderstanding what the result should be? Or I am just "doing it wrong"? My end goal here is to be able to display the resulting threads in some sort of directed graph using D3 – but that is not going to happen if I can't get the data set up correctly.
function makeThread(emails) {
var thread = jwz.messageThread().thread(emails.map(
function (message) {
return jwz.message(message.subject, message.messageId, message.references);
}
));
console.log('thread',thread);
}
It's pretty unclear how it works, but I managed to write some code that prints the "thread tree":
function recurse(node, level) {
level = level || 0;
let prefix = '\t'.repeat(level);
(node.children || []).forEach(function(child) {
child.children = child.children || [];
console.log(prefix, level ? '' : '-', child.message ? child.message.subject : '??', `[${ child.children.length }]`);
return recurse(child, level + 1);
});
}
recurse(jwz.messageThread().thread(messages));
(messages is an array of jwz.message() objects, similar to how you're creating it)
I am using Sigma.js with the cypher plugin to visualise my neo4j database. After following the simple example here https://github.com/jacomyal/sigma.js/blob/master/examples/load-neo4j-cypher-query.html , it is working well. I edited the plugin so that the graph labels displayed are the names of my neo4j nodes, however I would also like to show the other node properties when clicking on the label or node.I am quite new to JavaScript so would like to know if this is possible for a beginner like me to do and if it is where is the best place for me to start.
You have to register an event on the click or hover node.
There is an example into sigmajs for event : https://github.com/jacomyal/sigma.js/blob/master/examples/events.html
This is a short code that demonstrate how to make this. Replace the alert method by what you want.
sigma.bind('overNode', function(event) {
alert(event.data.node);
});
If you just want to discover your database, take a look at tank-browser : https://www.npmjs.com/package/tank-browser
Cheers
You have to edit Cypher plugin
First: Define var let's assume we will call it "has" at the beginning of the file.
Second: You should add ul in your html and add class to it called 'popover'
Third: Add to cypherCallback method you should add inside else if (typeof sig === 'object')
sig.graph.read(graph);
sig.bind('clickNode', function(e) {
var clicknode = e.data.node;
// empty the printed list
$('.popover').empty();
has='';
// create the tlis tof prop. from returend Object
for(var keys in clicknode.neo4j_data ){
$('.popover').append(' <li>' + keys + ' = '+ clicknode.neo4j_data[keys] + '</li>');
has+= 'n.' +keys + '="'+ clicknode.neo4j_data[keys] + '"AND ';
}
$('.popover').show();
});
sig.bind('clickStage', function(e) {
$('.popover').hide();
});
Suppose I have created several widgets (mywidget1, mywidget2, ...) and that all have a method with the same name (doSomething).
To invoke the method I can use:
$("#elem").widget1("doSomething");
but this way I need to know the name of the widget (in the example widget1).
If I have an array with multiple instances of the various widgets, how can I invoke on each one the method "doSomething" without knowing the name of the widget?
You can't. Two options for you:
Store them in separate arrays (one array for widget1, another for widget2), or
Store objects in the arrays containing the information about which widget relates to that entry
Here's an example of #2
var list = [
{widget: "widget1", element: $("#elem")},
{widget: "widget2", element: $(".some-selector")},
{widget: "widget2", element: $("#another")},
{widget: "widget1", element: $("div .target")}
];
$.each(list, function(i, entry) {
entry.element[entry.widget]("doSomething");
});
In theory I suppose you could do something like the following:
var widgets = [widget1, widget2, widget3]; // etc, will assume they are defined already
// Access each Widget, now widget points to each of the widgets
// So we dont need to know the actual name like widget1, widget2 etc
widgets.forEach(function (widget) {
$('#elem').widget('doSomething'); // Call the doSomething method of this widget
$('#elem').widget.call(null, 'doSomething'); // Try this if the above fails
$('#elem').call(widget, 'doSomething'); // Or maybe this :)
}
Anyway try the above, of the top of my head im not sure which will work. I think what you are trying to do might be a bit difficult to implement, so sorry if it doesnt work. Hopefully it will :)
you can have an object of functions and get the key value dynamically to use the particular function
widgets = {
widget1 : function(value){return value;},
widget2 : function(value){return value+1},
widget3 : function(value){return value+2}
}; //you can have your list of functions say widgets1,2,3....
for(var k in widgets ){
console.log(widgets[k](1));
} //to get the function name you can use the key name in the object
Example on https://gist.github.com/vishnu667/44063d64f2d1210c26c9
you can also call the function if you know the key
widgets['widget2'](10); //to directly call the function if you know the key
to Dynamically add more widgets use
function add_widget(name,widgetFunction){ //function to add widget
widgets[name]=widgetFunction;
}
add_widget("widget4",function(value){return value+10;}); //adds a new widget to the widgets list
I found this solution:
before:
var tmp = $("#elem").widget1();
myarray[i] = tmp;
now:
var tmp = $("#elem").widget1();
myarray[i] = tmp.data(ui-widget1);
in this way it is possible to directly call the method:
myarray[x].doSomething();
what do you think?
can be an efficient solution?
thanks to all
right now i am at a point where i feel that i need to improve my javascript skills because i already see that what i want to realize will get quite complex. I've iterrated over the same fragment of code now 4 times and i am still not sure if it's the best way.
The task:
A user of a webpage can add different forms to a webpage which i call modules. Each form provides different user inputs and needs to be handled differently. Forms/Modules of the same type can be added to the list of forms as the user likes.
My current solution:
To make the code more readable and seperate functions i use namespaced objects. The first object holds general tasks and refers to the individual forms via a map which holds several arrays where each contains the id of a form and the reference to the object which holds all the functions which need to be performed especially for that kind of form.
The structure looks more or less similar to this:
var module_handler = {
_map : [], /* Map {reference_to_obj, id} */
init: function(){
var module = example_module; /* Predefined for this example */
this.create(module);
},
create: function(module) {
//Store reference to obj id in map
this._map.push([module,id = this.createID()]);
module.create(id);
},
createID: function(id) {
//Recursive function to find an available id
},
remove: function(id) {
//Remove from map
var idx = this._map.indexOf(id);
if(idx!=-1) this._map.splice(idx, 1);
//Remove from DOM
$('#'+id+'').remove();
}
}
var example_module = {
create: function(id) {
//Insert html
$('#'+id+' > .module_edit_inner').replaceWith("<some html>");
}
}
Now comes my question ;-)
Is the idea with the map needed?
I mean: Isn't there something more elegant like:
var moduleXYZ = new example_module(id)
which copies the object and refers only to that form.... Something more logical and making speed improvements?? The main issue is that right now i need to traverse the DOM each time if i call for example "example_module.create() or later on any other function. With this structure i cant refer to the form like with something like "this"???
Do you see any improvements at this point??? This would help me very much!!! Really i am just scared to go the wrong way now looking at all the stuff i will put on top of this ;-)
Thank You!
I think you're looking for prototype:
=========
function exampleModule(id)
{
this.id = id;
}
exampleModule.prototype.create = function()
{
}
=========
var module1 = new exampleModule(123);
module1.create();
var module2 = new exampleModule(456);
module2.create();