requirejs: load script/module from a web service - javascript

I have a WebService that query a SQL database. In a sql table, I store some javascript and I want to use it in a webpage using RequireJS.
I try this :
var url = "http://localhost:64952/breeze/app/Objectss?$filter=Id%20eq%201&$select=Script";
require([url], (test) => {
debugger
arguments[0];
});
The server respond correctly :
http://i.stack.imgur.com/05lE7.png
But I'm not sure RequireJS is able to load script like this.
I try something else :
var req = breeze.EntityQuery.from("Commands")
.where("Id", "eq", "1")
.select("Script");
dataservice.manager.executeQuery(req)
.then((res : breeze.QueryResult) => {
if (res.results[0]) {
require([(<any>res.results[0]).Script], (hekki) => {
debugger
});
}
});
Doesn't work too...
Do you have any idea to help me please ?!

Create a requirejs plugin responsible for loading dependencies via the breeze api you've put together...
breezeloader.js:
define({
load: function (name, req, onload, config) {
// load the script using the breeze api you've put together...
var query = breeze.EntityQuery
.from("Commands")
.where("Id", "eq", name)
.select("Script");
dataservice.manager.executeQuery(query)
.then((queryResult: breeze.QueryResult) => {
var text = queryResult.results[0].Script;
// Have RequireJS execute the JavaScript within
//the correct environment/context, and trigger the load
//call for this resource.
onload.fromText(text);
});
}
});
express dependencies that should be loaded with the breeze loader using the requirejs plugin syntax:
require(['breezeloader!1', 'jquery', 'foo'], function (hekki, jquery, foo) {
...
});

Related

Loading a JSON into AngularJS Project Globally

The angular project I am working on is adding a configuration file to it. The configuration file is loaded as a JSON, it contains strings that will be replacing the static strings that are currently used in the current version of the project. There is multiple modules where the JSON's data needs to be used, what would be the best way to make the JSON file global throughout the project? I was thinking about loading it separately in each module using a HTTP GET, but I need the JSON to be loaded before everything else.
Thanks.
You probably can use a service. define a object on the scope and on that define the JSON. create a function which returns the JSON and inject it wherever the need arises. Implementation maybe like:
app.service("commonService", ["$log", function($log){
this.myConfiguration = {
id:"0",
name:"abc"
};
this.mystatic = function(){
return myConfiguration;
}
}
Now you can inject it and use in a controller as:
app.controller("mycontroller", function($scope, commonService){
$scope.static = commonService.myStatic();
//other code here
});
you can use value:
// create the module as usual
angular.module("myapp",[/*...*/]);
// on any other app point, set your json:
angular.module("myapp").value("myjson",{/*...*/});
If you don't need is before you do any routing you could use a service. This is what a config service could look like:
(untested)
app.service('ConfigService', function ($q, $http) {
// loads the config file
this.loadConfig: function() {
var deferred = $q.defer();
if(angular.isDefined(this.config) && this.config.length){
deferred.resolve(this.config);
}
$http.get('config.json')
.success(function(response) {
this.config = response;
deferred.resolve(this.config);
})
.error(function(){
deferred.reject('Could not load "config.json" file');
});
return deferred.promise;
};
// returns a config setting
this.get: function(key){
// if the config is not loaded yet, load it and call self
if(!angular.isDefined(this.config) || !this.config.length){
this.loadConfig().then(function(){
return this.get(key);
})
}
// config is loaded. Return requested key
if(angular.isDefined(config[key])){
return config[key];
}else{
console.error( 'Could not load config value: ' + key );
return false;
}
};
});

local PDF file scraping in node.js

I have uploaded a pdf via a MEAN stack web application using fs. I want to extract certain fields from the pdf and display them on the web app. I have looked at a couple npm packages like pdf.js, pdf2json. I can't figure out the documentation and javascript callbacks used in the examples available. Please help!
I hope I can help answer your question. Using pdf2json can be used to parse a pdf and extract the text. There are a couple of steps that need to be taken to get it working. I have adapted the example from https://github.com/modesty/pdf2json.
The setup is to install pdf2json in the node app, and also underscore. The example page didn't explain the need to define your own callback functions. It also used self instead of this to register them. So, with the appropriate changes the code to extract all the text from the pdf will be something like this:
// Get the dependencies that have already been installed
// to ./node_modules with `npm install <dep>`in the root director
// of your app
var _ = require('underscore'),
PDFParser = require('pdf2json');
var pdfParser = new PDFParser();
// Create a function to handle the pdf once it has been parsed.
// In this case we cycle through all the pages and extraxt
// All the text blocks and print them to console.
// If you do `console.log(JSON.stringify(pdf))` you will
// see how the parsed pdf is composed. Drill down into it
// to find the data you are looking for.
var _onPDFBinDataReady = function (pdf) {
console.log('Loaded pdf:\n');
for (var i in pdf.data.Pages) {
var page = pdf.data.Pages[i];
for (var j in page.Texts) {
var text = page.Texts[j];
console.log(text.R[0].T);
}
}
};
// Create an error handling function
var _onPDFBinDataError = function (error) {
console.log(error);
};
// Use underscore to bind the data ready function to the pdfParser
// so that when the data ready event is emitted your function will
// be called. As opposed to the example, I have used `this` instead
// of `self` since self had no meaning in this context
pdfParser.on('pdfParser_dataReady', _.bind(_onPDFBinDataReady, this));
// Register error handling function
pdfParser.on('pdfParser_dataError', _.bind(_onPDFBinDataError, this));
// Construct the file path of the pdf
var pdfFilePath = 'test3.pdf';
// Load the pdf. When it is loaded your data ready function will be called.
pdfParser.loadPDF(pdfFilePath);
I am running the code out of my server side controller.
module.exports = (function() {
return {
add: function(req, res) {
var tmp_path = req.files.pdf.path;
var target_path = './uploads/' + req.files.pdf.name;
fs.rename(tmp_path, target_path, function(err) {
if (err) throw err;
// delete the temporary file, so that the explicitly set temporary upload dir does not get filled with unwanted files
fs.unlink(tmp_path, function() {
if (err) throw err;
//edit here pdf parser
res.redirect('#/');
});
})
},
show: function(req, res) {
var pdfParser = new PDFParser();
var _onPDFBinDataReady = function (pdf) {
console.log('Loaded pdf:\n');
for (var i in pdf.data.Pages) {
var page = pdf.data.Pages[i];
// console.log(page.Texts);
for (var j in page.Texts) {
var text = page.Texts[j];
// console.log(text.R[0].T);
}
}
console.log(JSON.stringify(pdf));
};
// Create an error handling function
var _onPDFBinDataError = function (error) {
console.log(error);
};
pdfParser.on('pdfParser_dataReady', _.bind(_onPDFBinDataReady, this));
// Register error handling function
pdfParser.on('pdfParser_dataError', _.bind(_onPDFBinDataError, this));
// Construct the file path of the pdf
var pdfFilePath = './uploads/Invoice_template.pdf';
// Load the pdf. When it is loaded your data ready function will be called.
pdfParser.loadPDF(pdfFilePath);
},
//end controller
}

Better place to setup an initialisation in SailsJS

I'm new to Sails and don't know exactly where to put the initialisation of an object to be unique in all the app. After reading the docs I assumed that I can have it in the global sails object, but not sure if is the better place.
I'm using the new Appcelerator ArrowDB to store my users and objects. Docs talk about declare the appropriate vars and use it, with the APP_KEY.
var ArrowDB = require('arrowdb'),
arrowDBApp = new ArrowDB('<App Key>');
function login(req, res) {
var data = {
login: req.body.username,
password: req.body.password,
// the req and res parameters are optional
req: req,
res: res
};
arrowDBApp.usersLogin(data, function(err, result) {
if (err) {
console.error("Login error:" + (err.message || result.reason));
} else {
console.log("Login successful!");
console.log("UserInfo: " + JSON.stringify(result.body.response.users[0]));
}
});
}
But I will need to use constantly that arrowDBApp var to create, update, delete objects in the database, so I think the best way is to initialize it in the starting script app.js and share across the app.
I tried it, but I was not able to store it in the sails var, it seems that this var is not available (or lose its config) until sails.lift() is executed.
This code (app.js file) shows nothing in the console:
// Ensure we're in the project directory, so relative paths work as expected
// no matter where we actually lift from.
process.chdir(__dirname);
// Ensure a "sails" can be located:
(function() {
var sails;
try {
sails = require('sails');
} catch (e) {
console.error('To run an app using `node app.js`, you usually need to have a version of `sails` installed in the same directory as your app.');
console.error('To do that, run `npm install sails`');
console.error('');
console.error('Alternatively, if you have sails installed globally (i.e. you did `npm install -g sails`), you can use `sails lift`.');
console.error('When you run `sails lift`, your app will still use a local `./node_modules/sails` dependency if it exists,');
console.error('but if it doesn\'t, the app will run with the global sails instead!');
return;
}
// Try to get `rc` dependency
var rc;
try {
rc = require('rc');
} catch (e0) {
try {
rc = require('sails/node_modules/rc');
} catch (e1) {
console.error('Could not find dependency: `rc`.');
console.error('Your `.sailsrc` file(s) will be ignored.');
console.error('To resolve this, run:');
console.error('npm install rc --save');
rc = function () { return {}; };
}
}
// My own code
var APP_KEY = 'mykey';
var ArrowDB = require('arrowdb');
sails.arrowDBApp = new ArrowDB(APP_KEY);
console.log("Hi" + JSON.stringify(sails));
// Start server
sails.lift(rc('sails'));
console.log("Finish");
})();
No "HI" and no "Finish" are printed. If I try to use sails.arrowDBApp in another controller, it is undefined.
Tips are welcome.
It's not advisable to modify app.js unless you really need to.
The usual space to save all configuration information (e.g. the APP_KEY) is in the config directory in your project root.
One-time initializations (e.g. ArrowDB initialization) can be added to config/bootstrap.js.
Update
In config/arrowdb.js (you need to create this file yourself):
module.exports.arrowdb = {
APP_KEY: 'yourappkey',
ArrowDBApp: null
};
In config/bootstrap.js:
var ArrowDB = require('arrowdb');
module.exports.bootstrap = function(next){
sails.config.arrowdb['ArrowDBApp'] = new ArrowDB(sails.config.arrowdb['APP_KEY']);
next(); // Don't forget to add this
};
In your controller:
'task': function(req, res, next) {
sails.config.arrowdb['ArrowDBApp'].usersLogin(...);
// and so on.
// You could also add something like
// var ADB = sails.config.arrowdb['ArrowDBApp'];
// at the top in case you need to use it on and on.
}
Use config/bootstrap.js to initialize something before Sails lifted. Sometimes if we want to put something in global variable, this approach is good to use, like define/ override native Promise with Bluebird Promise.
Use api/services to put some method or other things that you will use regularly in your code (controllers, models, etc.), like Mail Service, that handle sending email within your application.
Use config at config folder to predefined something at sails.config[something]. It can be an object, function, or whatever in order to become configurable, like put Twitter API Key to use Twitter REST API.
To achieve what you wanted, I'll try to use service and bootstrap.js. Try this example.
Create service file at api/services/ArrowDBService.js
Put with this code:
var ArrowDB = require('arrowdb'),
arrowDBApp = new ArrowDB('<App Key>');
module.exports = {
arrowDBApp : arrowDBApp,
login : function (req, res) {
var data = {
login: req.body.username,
password: req.body.password,
// the req and res parameters are optional
req: req,
res: res
};
arrowDBApp.usersLogin(data, function(err, result) {
if (err) {
console.error("Login error:" + (err.message || result.reason));
} else {
console.log("Login successful!");
console.log("UserInfo: " + JSON.stringify(result.body.response.users[0]));
}
});
}
};
Now you can use it by sails.services.arrowdbservice.login(req,res) or simply ArrowDBService.login(req,res) (notice about case sensitive thing). Since I don't know about ArrowDB, so you may explore by yourself about login method that your example provide.

Alloy Titanium & Google Cloud Endpoint

I would like to know how (the right way) to work with Google Cloud Endpoint in an Alloy Titanium application. And I would like to use the library that Google has for the API endpoints.
I am new to Alloy and CommonJS, therefore trying to figure out the right way to do this.
From my understanding Alloy prefers (or only allows) including javascript via modules (CommonJS - exports...).
var module = require('google.js');
google.api.endpoint.execute();
This would be the way CommonJS would expect things to work. Although in the google javascript library it just creates a global variable called "gapi".
Is there a way, I can include this file ?
Is there a way, I can create global variables ?
Should I stay away from creating them in first place ?
Thanks !
The client.js library that Google has for the API endpoints can be run only from browsers (Titanium.UI.WebView in this case), it can't be run directly from Titanium code since it contains objects not available in Titanium Appcelerator.
Also, using a Google Cloud Endpoint into an Alloy Titanium application requires having the js code available into the project at compile time, as it is used by Titanium to generate the native code for the desired platforms.
To anwser your questions:
Is there a way, I can include this file ?
No, if you plan to run the code as Titanium code, for the reasons mentioned above. Instead you could use the following code snippet to connect to a Google Cloud Endpoint:
var url = "https://1-dot-projectid.appspot.com/_ah/api/rpc";
var methodName = "testendpoint.listGreetings";
var apiVersion = "v1";
callMethod(url, methodName, apiVersion, {
success : function(responseText)
{
//work with the response
},
error : function(e) { //onerror do something
}
});
function callMethod(url, methodName, apiVersion, callbacks) {
var xhr = Titanium.Network.createHTTPClient();
xhr.onload = function(e) {
Ti.API.info("received text: " + this.responseText);
if (typeof callbacks.success === 'function') {
callbacks.success(this.responseText);
}
};
xhr.onerror = function(e) {
Ti.API.info(JSON.stringify(e));
//Ti.API.info(e.responseText);
if (typeof callbacks.error === 'function') {
callbacks.error(e);
}
};
xhr.timeout = 5000; /* in milliseconds */
xhr.open("POST", url, true);
xhr.setRequestHeader('Content-Type', 'application/json-rpc');
//xhr.setRequestHeader('Authorization', 'Bearer ' + token);
var d = [{
jsonrpc: '2.0',
method: methodName,
id: 1,
apiVersion: apiVersion,
}];
Ti.API.info(JSON.stringify(d));
// Send the request.
xhr.send(JSON.stringify(d));
}
Yes, if you use the embeded device's browser like this (as can be found in web client GAE samples)
webview = Titanium.UI.createWebView({
width : '100%',
height : '100%',
url : url // put your link to the HTML page
});
, to call your server HTML page which should contain:
script src="https://apis.google.com/js/client.js?onload=init">
Is there a way, I can create global variables ?
Yes, insert into the app/alloy.js file the global variables, see the default comments in the file:
// This is a great place to do any initialization for your app
// or create any global variables/functions that you'd like to
// make available throughout your app. You can easily make things
// accessible globally by attaching them to the Alloy.Globals
// object. For example:
//
Alloy.Globals.someGlobalFunction = function(){};
Alloy.Globals.someGlobalVariable = "80dp";
Should I stay away from creating them in first place ?
I suppose you are reffering to global variables containing the module code for connecting to GAE enpoind methods. It's your call, here is how you can use them.
a) Create a file named jsonrpc.js in the app/lib folder of your Titanium project, put the following code into it, and move the function code from above as the function body:
JSONRPCClient = function () {
};
JSONRPCClient.prototype = {
callMethod : function (url, methodName, apiVersion, callbacks) {
// insert the function body here
}
};
exports.JSONRPCClient = JSONRPCClient;
b) Into app/alloy.js file define your global variable:
Alloy.Globals.JSONRPCClient = require('jsonrpc').JSONRPCClient;
c) Use it (eg. from your controller js files):
var client = new Alloy.Globals.JSONRPCClient();
var url = "https://1-dot-projectid.appspot.com/_ah/api/rpc";
var methodName = "testendpoint.listGreetings";
var apiVersion = "v1";
client.callMethod(url, methodName, apiVersion,
{success: function(result) {
//result handling
Ti.API.info('response result=', JSON.stringify(result));
//alert(JSON.stringify(result));
},
error: function(err) {
Ti.API.info('response out err=', JSON.stringify(err));
//error handling
}
});

How to execute an external script in jsdom

I have a method in a products.js file like so:
var handler = function(errors, window) {...}
and would like to execute it within a jsdom env callback:
jsdom.env({
html : "http://dev.mysite.com:3000/products.html",
scripts : [ "http://code.jquery.com/jquery.js", "page-scrapers/products.js" ],
done : function(errors, window) {
handler(errors, window)
}
});
When executed, it tells me 'handler is not defined'. Am I getting close?
Context of the problem is to scrape data from an existing web site. We want to associate a javascript scraper for each page, and access the scraped data via URLs served up via a node.js server.
As suggested by Juan, the key is using node.js modules. The bulk of the hander method is exported from product.js:
exports.handler = function(errors, window, resp) {...
and then imported in the node.js-based server instance:
//note: subdir paths must start with './' :
var products = require('./page-scrapers/products.js');
This creates a reference to the method by name 'products.handler', which can then be called in the request handler:
var router = new director.http.Router({
'/floop' : {
get : funkyFunc
}
})
var funkyFunc = function() {
var resp = this.res
jsdom.env({
html : "http://dev.mySite.com:3000/products.html",
scripts : [ "http://code.jquery.com/jquery.js"],
done : function(errors, window) {products.handler(errors, window, resp)}
});
}
And that works.
If you want a variable to be accessible to another file, you have to export it. http://nodejs.org/api/modules.html
//products.js
exports.handler = function(window, error) {...}
// another.file.js
var products = require('products.js');
jsdom.env({
html : "http://dev.mysite.com:3000/products.html",
scripts : [ "http://code.jquery.com/jquery.js", "page-scrapers/products.js" ],
// This can be simplified as follows
done : products.handler
});
This sounds like a bad idea though, why would a handler be made into a global? I think you should restructure your code

Categories