How to programmatically render dustjs template server side in nodejs - dust.js

How I can render dustjs template programmatically in nodejs at server side.
dust.render("test", { data: "test" }, function(err, out) {
var datastring = out;
});
which doesn't seems working for me.

You need to make the template available in Node's JavaScript execution environment. Here is an example of how to make that happen:
var fs = require('fs');
var vm = require('vm');
var dust = require('dustjs-linkedin');
// Read the compiled Dust template.
var compiledTemplate = fs.readFileSync('path/to/compiled/dustTemplate.js');
// Execute the compiled Dust template to make it available
// in the current execution context
vm.runInThisContext(compiledTemplate);
// Render the Dust template.
dust.render('test', {data: 'test'}, function(err, out) {
console.log(out);
});

Related

Upload pictures with TinyMCE and RoR on protected page

I don't need a concret solution, but someone that gives me a closer hint to solve my problem. I have an ruby on rails 4 intranet application, that is login protected. In this application I have an editing page, where I also use TinyMCE. It has the ability to give it an URL where to send the picture to for uploading it (see here).
I implemented the upload routine with CarrierWave and it works great outside of TinyMCE. If it's possible I would also keep that plugin.
But as I said CarrierWave is currently not working with TinyMCE and an asynchronous upload.
So do you have an idea how I can upload an image, but with correct session token (asynchronously). And the picture URL that not saving the database, but in the text shown in TinyMCE. Is there a plugin that can help me or anything else?
If you need closer information please tell me.
Best regards
Marco
You have to use the image plugin for TinyMCE and set file_picker properties and callbacks, so you can attach files from client-side, rather than URL.
tinymce.init({
// Include image plugin on plugin list
plugins: [ 'image'],
// Include image button on toolbar
toolbar: ['image'],
// Enable title field in the Image dialog
image_title: true,
// Enable automatic uploads of images represented by blob or data URIs
automatic_uploads: true,
// URL of your upload handler
// (YOU SHOULD MAKE AN ENDPOINT TO RECEIVE THIS AND RETURN A JSON CONTAINING: {location: remote_image_url})
images_upload_url: '/text_images',
// Here we add custom filepicker only to Image dialog
file_picker_types: 'image',
// And here's your custom image picker
file_picker_callback: function(cb, value, meta) {
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('accept', 'image/*');
input.onchange = function() {
var file = this.files[0];
// Note: Now we need to register the blob in TinyMCEs image blob
// registry.
var id = 'blobid' + (new Date()).getTime();
var blobCache = tinymce.activeEditor.editorUpload.blobCache;
var blobInfo = blobCache.create(id, file);
blobCache.add(blobInfo);
// Call the callback and populate the Title field with the file name
cb(blobInfo.blobUri(), { title: file.name });
};
input.click();
}
});
Add text_images to your route.rb file:
match "text_images" => "text_images#create", via: :post
And create your proccessing action like this:
def create
if params[:file].class == ActionDispatch::Http::UploadedFile
#image = Picture.new(image: params[:file])
respond_to do |format|
if #image.save
format.json { render json: { "location": #image.image.url }.to_json, status: :ok }
else
format.json { render json: #image.errors, status: :unprocessable_entity }
end
end
end
end
This is a very crude implementation, you should make it more secure for your application context, validating and filtering large or invalid files!
UPDATE: There was a recent upgrade on the syntax for new versions of TinyMCE for the onchange function to include a result reader attribute on the create method of the blobCache object:
input.onchange = function() {
var file = this.files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
// Note: Now we need to register the blob in TinyMCEs image blob
// registry. In the next release this part hopefully won't be
// necessary, as we are looking to handle it internally.
var id = 'blobid' + (new Date()).getTime();
var blobCache = tinymce.activeEditor.editorUpload.blobCache;
var blobInfo = blobCache.create(id, file, reader.result);
blobCache.add(blobInfo);
// call the callback and populate the Title field with the file name
cb(blobInfo.blobUri(), { title: file.name });
};
};

Openlayers 3 vector source issue

Inside the ajax callback I have all the features as expected, but I don't have them outside.
What am I missing ?
var geojsonSource = new ol.source.Vector();
$.ajax('assets/data/data.geojson').then(function(response) {
var geojsonFormat = new ol.format.GeoJSON();
var features = geojsonFormat.readFeatures(response, {featureProjection: 'EPSG:4326'});
geojsonSource.addFeatures(features);
console.log(geojsonSource.getFeatures()); // this work
});
console.log(geojsonSource.getFeatures()); // this doesn't work
Everything's fine with your snippet. As #kryger said, AJAX is Asynchronous Javascript and XML. So, register a listener to know when your features are added to the source, like:
geojsonSource.on('addfeature', function(event){
console.log(geojsonSource.getFeatures());
});

Uploading an Image file via ajax in add-on panel

I'm trying desperately to create a Firefox add-on that posts a file with the field name "Filedata" to a particular PHP script which will only work if it sees a JPG in the $_FILE["Filedata"] variable.
I put a web form with a file browser into panel.html, then I take the image and turn it into a canvas which I turn into a blob and send to main.js. I would be happy to send the file directly from panel.js, but nothing at all happens (no error message either) when I attempt to so.
In main.js, I have this code but I get an error message that FormData doesn't exist in main.js. What to do?
function ajupload(mydata) {
var fd = new FormData();
fd.append("Filedata", mydata);
const {XMLHttpRequest} = require("sdk/net/xhr");
var myrequest = new XMLHttpRequest();
myrequest.open('POST', 'MYSITE/image.php?action=upload');myrequest.setRequestHeader("Content-type","application/x-www-form-urlencoded");
myrequest.upload.addEventListener("progress", function(e) {
var percentage = Math.round((e.loaded * 100) / e.total);
}, false);
myrequest.onreadystatechange=function()
{
if (myrequest.readyState==4 && myrequest.status==200)
{
console.log("Response" + myrequest.responseText);
}
}
myrequest.send(fd);
}

backbone.js load text file into a collection

This is first time I am using a framework for development and stuck with the very first step.
I am converting a Flex application to Javascript application and using backbone as framework.
I have to load a text file which is in name value format.
<!doctype html>
<html>
<head>
<script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js'></script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js'></script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.10/backbone-min.js'></script>
<script>
var ResourceBundleCollection = Backbone.Collection.extend({
url:'ResourceBundle.txt',
});
var resourceBundleCollection = new ResourceBundleCollection();
resourceBundleCollection.fetch();
</script>
</head>
<body>
</body>
</html>
The ResourceBundle.txt includes the content in following format
location_icon=../../abc/test.png
right_nav_arrow_image=assets/images/arrow.png
right_nav_arrow_image_visible=true
It is throwing following error
not well-formed
I could load the text file easily using JQuery and parse it
$.ajax({
type : "GET",
url : "ResourceBundle.txt",
datatype : "script",
success : resourceXMLLoaded
});
and parse it using the following code
var lines = txt.split("\n");
for(var i=0;i<lines.length;i++) {
if(lines[i].length > 5) {
var _arr = lines[i].split("=");
resourceBundleObj[$.trim(_arr[0])] = $.trim(_arr[1]);
}
}
Please advice how to achieve the same results in backbone.js
If you MUST use plain text to support this, you can override Backbone.Collection.parse to achieve what you need.
In addition to that, you may also want to create a ResourceBundleModel to host each item in the ResourceBundleCollection.
You can see a demo here: http://jsfiddle.net/dashk/66nkF/
Code for Model & Collection is here:
// Define a Backbone.Model that host each ResourceBundle
var ResourceBundleModel = Backbone.Model.extend({
defaults: function() {
return {
name: null,
value: null
};
}
});
// Define a collection of ResourceBundleModels.
var ResourceBundleCollection = Backbone.Collection.extend({
// Each collection should know what Model it works with, though
// not mandated, I guess this is best practice.
model: ResourceBundleModel,
// Replace this with your URL - This is just so we can demo
// this in JSFiddle.
url: '/echo/html/',
parse: function(resp) {
// Once AJAX is completed, Backbone will call this function
// as a part of 'reset' to get a list of models based on
// XHR response.
var data = [];
var lines = resp.split("\n");
// I am just reusing your parsing logic here. :)
for (var i=0; i<lines.length; i++) {
if (lines[i].length > 5) {
var _arr = lines[i].split("=");
// Instead of putting this into collection directly,
// we will create new ResourceBundleModel to contain
// the data.
data.push(new ResourceBundleModel({
name: $.trim(_arr[0]),
value: $.trim(_arr[1])
}));
}
}
// Now, you've an array of ResourceBundleModel. This set of
// data will be used to construct ResourceBundleCollection.
return data;
},
// Override .sync so we can demo the feature on JSFiddle
sync: function(method, model, options) {
// When you do a .fetch, method is 'read'
if (method === 'read') {
var me = this;
// Make an XHR request to get data
// Replace this code with your own code
Backbone.ajax({
url: this.url,
method: 'POST',
data: {
// Feed mock data into JSFiddle's mock XHR response
html: $('#mockData').text()
},
success: function(resp) {
options.success(me, resp, options);
},
error: function() {
if (options.error) {
options.error();
}
}
});
}
else {
// Call the default sync method for other sync method
Backbone.Collection.prototype.sync.apply(this, arguments);
}
}
});
Backbone is designed to work with a RESTful API through JSON natively. It however is a library that is flexible enough to fit your need, given enough customization.
By default a collection in Backbone will only accept a JSON formatted collection.
So you need to convert your input to JSON format:
[{"name": "name", "value": "value},
{"name": "name", "value": "value}, ...
]
Of course you can override the default behaviour:
Overriding backbone's parse function

How to parse a XML string in a Firefox addon using Add-on SDK

I am trying to create a FF AddOn that brings some XML data from a website. But I can't find a way to parse my RESPONSE. First I used DOMParser but I get this error:
ReferenceError: DOMParser is not defined.
Someone suggested to use XMLHttpRequest, because the parsing is done automatically but then I get this other error:
Error: An exception occurred. Traceback (most recent call last):
File
"resource://jid0-a23vmnhgidl8wlymvolsst4ca98-at-jetpack/api-utils/lib/cuddlefish.js",
line 208, in require
let module, manifest = this.manifest[base], requirer = this.modules[base]; TypeError: this.manifest is undefined
I really don't know what else to do. I must note that I am using the AddOn Builder to achieve this.
Below the code that doesn't seem to work.
Option 1:
exports.main = function() {
require("widget").Widget({
id: "widgetID1",
label: "My Mozilla Widget",
contentURL: "http://www.mozilla.org/favicon.ico",
onClick: function(event) {
var Request = require("request").Request;
var goblecontent = Request({
url: "http://www.myexperiment.org/search.xml?query=goble",
onComplete: function (response) {
var parser = new DOMParser();
var xml = parser.parseFromString(response.text, "application/xml");
var packs = xml.getElementsByTagName("packs");
console.log(packs);
}
});
goblecontent.get();
}
});
};
Option 2:
exports.main = function() {
require("widget").Widget({
id: "widgetID1",
label: "My Mozilla Widget",
contentURL: "http://www.mozilla.org/favicon.ico",
onClick: function(event) {
var request = new require("xhr").XMLHttpRequest();
request.open("GET", "http://www.myexperiment.org/search.xml?query=goble", false);
request.send(null);
if (request.status === 200) {
console.log(request.responseText);
}
}
});
};
DOMParser constructor isn't defined in the context of SDK modules. You can still get it using chrome authority however:
var {Cc, Ci} = require("chrome");
var parser = Cc["#mozilla.org/xmlextras/domparser;1"].createInstance(Ci.nsIDOMParser);
nsIDOMParser documentation.
That said, your approach with XMLHttpRequest should work as well. You used the new operator incorrectly however, the way you wrote it a new "require object" is being created. This way it should work however:
var {XMLHttpRequest} = require("xhr");
var request = new XMLHttpRequest();
Please consider using an asynchronous XMLHttpRequest object however, use request.onreadystatechange to attach your listener (the xhr module currently doesn't support other types of listeners or addEventListener).
If you use XMLHttpRequest (available via the xhr module) you can easily avoid the use of DOMParser. Bellow I provide an example supposing request is an XMLHttpRequest object which request is successfully completed:
Instead of:
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(request.responseText, "application/xml");
Use:
var xmlDoc = request.responseXML;
An then you can:
var packs = xmlDoc.getElementsByTagName("packs");
console.log(packs);
Or whatever.

Resources