publishCreate - messages not broadcasted - sails.js

I stuck on publishCreate message broadcasting and have no idea what I am doing wrong.
Created a simple model called Sample:
module.exports = {
attributes: {
device: 'string',
value: 'float'
},
afterCreate: function(sample, next) {
console.log("afterCreate called");
Sample.publishCreate({value: sample.value});
console.log("publishCreate sent");
next();
}
};
Didnt find in the documentation if models do publishCreate automatically so I added afterCreate.
Then I created following view:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="/styles/iphone.css">
<!-- Bring in the socket.io client -->
<script type="text/javascript" src="/js/socket.io.js"></script>
<!-- then beef it up with some convenience logic for talking to Sails.js -->
<script type="text/javascript" src="/js/sails.io.js"></script>
<!-- listen on socket.io for incoming messages -->
<script type="text/javascript" src="/js/app.js"></script>
<script type="text/javascript">
socket.on('message', function(msg){
alert('message received');
});
</script>
</head>
<body>
<div class="block" style="height: 320px;">
<div class="centered">
<h1><%= temp %>°</h1>
</div>
</div>
</body>
</html>
Theoretically now if I call the view in the browser and then in the other browser tab I call
http://localhost:1337/sample/create?device=AA&value=10.0
a message should be received on the client side in the above view but nothing happens.
I know from the messages that sockets are connected and publishCreate is called when new Sample is created.
What can be a reason? Do I also have to do something in the controller when calling res.view() ?

Did you explicitly declare your publishCreate in your create action of the controller?
'create': function(req,res,next){
Sample.create(req.params.all(), function sampleCreated(err,sample){
if(err){console.log(err); }
Sample.publishCreate({
id:sample.id,
device: sample.device,
value: sample.value
});
});
},
You should probably explicitly declare the data points that you want to publish. Here I've set the Id, device, and value to be published explicitly. Blueprints and automatic controller mapping is useful, but it might be really unstable and unreliable sometimes, especially with the lack of documentation. Better to be specific.

The likely problem here is that the controller action that contains the subscribe call is being run in response to an HTTP request, not a socket request. req.socket is meaningless when the request is via HTTP; the server has no idea what socket was used. In order for subscribe to work, the request has to be made over a socket connection, e.g. using the socket.get method in the sails.io.js library.

we would need to use Model.watch(req) in order to subscribe to Model class. Then we will receive publishCreate() broadcasts.
http://sailsjs.org/documentation/reference/web-sockets/resourceful-pub-sub/watch

Related

openui5 ActionSelect not showing ListItems in drop list

I am trying to use the sap.m.ActionSelect within my application (as I like the combination of selection and action buttons). However, even within this simple test, I cannot get the drop list to show anything other than the first item. I am sure I am doing something completely dumb, but this one has me beaten. If anyone can spot the deliberate mistake I would be grateful!
<!doctype html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<title>ActionSelect</title>
<script id="sap-ui-bootstrap" src="../openui5/sap-ui-core.js" data-sap-ui-theme="sap_bluecrystal" data-sap-ui-libs="sap.ui.commons"
data-sap-ui-libs="sap.ui.unified" data-sap-ui-libs="sap.m"
data-sap-ui-resourceroots='{
"sparqlish":"../",
"sparqlish":"../sparqlish",
"Components":"../",
"Components":"../Components"
}'
data-sap-ui-xx-bindingSyntax="complex" type="text/javascript"></script>
<script type="text/javascript">
jQuery.sap.require("sap.m.ActionSelect");
jQuery.sap.require("sap.m.Button");
this.oServiceSelect = new sap.m.ActionSelect();
var oItem = new sap.ui.core.ListItem("Country1");
oItem.setText("Canada");
this.oServiceSelect.addItem(oItem);
oItem = new sap.ui.core.ListItem("Country2");
oItem.setText("Deutschland");
this.oServiceSelect.addItem(oItem);
oItem = new sap.ui.core.ListItem("Country3");
oItem.setText("England");
this.oServiceSelect.addItem(oItem);
oItem = new sap.ui.core.ListItem("Country4");
oItem.setText("Россия");
this.oServiceSelect.addItem(oItem);
this.oServiceSelect.setEnabled(true);
this.oServiceSelect.placeAt("serviceMenu");
this.oServiceSelect.addButton(new sap.m.Button({
text : "Action 1",
press : function(){alert("Action 1")}
}));
this.oServiceSelect.addButton(new sap.m.Button({
text : "Action 2",
press : function(){alert("Action 2")}
}));
</script>
</head>
<body>
<div id="serviceMenu"></div>
</body>
</html>
You have several issues in the code. First, you are loading the libs at bootstrap with three different attributes. This is wrong! Instead simply use one attribute and list the libs you want separated by comma.
Another issue in the code is that you are loading both sap.ui.commons and sap.m. As a rule of thumb you should never ever mix sap.ui.commons and sap.m!!! That's very important.
In your case you could and definitely should even completely remove sap.ui.commons because as far as I can see it from your code you are not using it anyway.
It appears that the order in which one declares the data-sap-ui-libs is important. The original order in the example above was:
data-sap-ui-libs="sap.ui.commons"
data-sap-ui-libs="sap.ui.unified"
data-sap-ui-libs="sap.m"
However if I reorder these to the following, with data-sap-ui-libs="sap.m" everything works well
data-sap-ui-libs="sap.m"
data-sap-ui-libs="sap.ui.commons"
data-sap-ui-libs="sap.ui.unified"

ERR_FILE_NOT_FOUND observed when SC.oEmbed is Called

I wonder to use SC.oEmbed to play sound from SoundCloud.But when I use it, I always get ERR_FILE_NOT_FOUND error.
I put my Source Code in Jsfiddle: http://jsfiddle.net/n2sVk/, it works OK. But when I save it to a HTML file and open it with Chrome, the error would be observed.
The Source Code is shown as below:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta charset="UTF-8">
</head>
<body>
<script src="http://connect.soundcloud.com/sdk.js"></script>
<div id="wrap"></div>
<script type="text/javascript">
SC.initialize({
client_id: "c202b469a633a7a5b15c9e10b5272b78",
redirect_uri: "http://connect.soundcloud.com/examples/callback.html"
});
SC.connect(function(){
console.log("connect " + "return");
SC.get("/me", function(me){
console.log("me.username:" + me.username);
console.log("me.description:" + me.description);
SC.get("/tracks", {limit: 1}, function(tracks){
console.log("get track return");
track = tracks[0];
console.log("track.uri: " + track.uri);
console.log("track.title: " + track.title);
SC.oEmbed(track.permalink_url,
{auto_play: true},
document.getElementById("wrap"));
});
});
});
</script>
</body>
Here is the error from Chrome:
GET file://soundcloud.com/oembed.json?auto_play=true&url=http%3A%2F%2Fsoundcloud.com%2Fyung-crusty-beats%2Fmystic-juice net::ERR_FILE_NOT_FOUND sdk.js:1
oEmbed response: null
This happens because when you are testing it locally, you are on "file:///" protocol.
The library's source code is using // in place of the protocol – this lets the library work on both http and https. However, when you access your code from a file as opposed to a webserver, the oembed function will probably not work.
The solution will be to run a local web server, such as Python simple server, which you'd run from the root folder of your project:
python -m SimpleHTTPServer

AngularJS and Rest Service

I've recently started experimenting with AngularJS. I am building a simple html5 application that updates a MySQL database.
[index.html]
<!DOCTYPE html>
<html ng-app="MyProject">
<head>
<title>My Project</title>
<link rel="stylesheet" href="css/main.css" type="text/css">
<script src="lib/angular-1.0.1.js"></script>
<script src="lib/angular-resource-1.0.1.js"></script>
<script src="js/controllers.js"></script>
<script src="js/services.js"></script>
</head>
<body>
<div id="main-content" ng-view>
</body>
</html>
I used the Slim framework to create a Rest Interface. My database has currently one table named location_types with two columns id and title. I have tested the Rest service in the browser so under api/locationtypes I get the following JSON:
[{"id":"1","title":"Airport"},{"id":"2","title":"Bus Station"}]
I create the service in AngularJS using the following code:
[services.js]
angular.module('myDB', ['ngResource']).
factory('LocationTypes', function($resource) {
var LocationTypes = $resource('http://localhost/project/api/locationtypes', {}, { query: {method: 'GET', isArray: true}});
return LocationTypes;
});
I also use the following code to create the app module:
[controllers.js]
angular.module('MyProject', ['myDB']).
config(function($routeProvider) {
$routeProvider.
when('/locationtypes', {controller: LocationTypesCtrl, templateUrl:'forms/locationtypes.html'}).
otherwise({redirectTo:'/locationtypes'});
});
function LocationTypesCtrl($scope, LocationTypes)
{
$scope.locationTypes = LocationTypes.query();
}
The problem is that I get no results after querying the service. The locationTypes array is of zero length when I debug. I am using the latest AngularJS release [1.0.1]. What do I miss?
Is your URL really 'http://localhost/project/api/locationtypes' or is it an external server?
If its external, then you have a CORS (cross origin) issue. Unless I'm missing something it looks correct to me.
Probably a CORS issue like Dan said.
You can bypass this by adding the following to your module config.
.config(function($httpProvider){
delete $httpProvider.defaults.headers.common['X-Requested-With'];
})
Deleting the headers set by Angular should resolve the CORS issue.
You should also add a .htaccess file in your api folder. And add this:
Header set Access-Control-Allow-Origin "*"

knockout and form's input values

I have been pretty much in love with knockout lately, and here is my first copy-and-paste source snip :rolleyes:. Without luck, I fail to make it work on the local host server, although I already set up the knockout.js in the same directory of the file.php. I hope someone could help.
<script type="text/javascript" src="knockout210.js"></script>
<script type="text/javascript">
var ViewModel=function(first, last)
{
this.firstName=ko.observable(first);
this.lastName=ko.observable(last);
this.fullName=ko.computed(function()
{
return this.firstName()+" "+this.lastName();
},this);
}
ko.applyBindings(new ViewModel("Planet","Earth"));
</script>
<p>First Name: <input data-bind="value:firstName"/></p>
<p>Last Name: <input data-bind="value:lastName"/></p>
<h2>Hello, <span data-bind="text:fullName"></span>!</h2>
I've setup your demo on jsfiddle. It runs perfectly fine. If what you posted is the actual HTML on your page I'd suggest that you include the html, head, and body tags and make sure that knockout210.js is actually being referenced correctly. Also, if you are having trouble with php or whatever, just make a plain old HTML file and it should run.
Here is your exact code that works: http://jsfiddle.net/lucuma/wD8jE/

how do I use XUI tween?

I don't understand how to use XUI tween. On the xui website, they give the following example code:
x$('#box').tween([{left:'100px', backgroundColor:'green', duration:.2 }, { right:'100px' }]);
What is that supposed to do? I created a <div id="box"></div>, ran the line of js code above, but nothing happened. Here's my complete code:
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="text/javascript" src="xui.min.js"></script>
<script type="text/javascript">
x$('#box').tween([{left:'100px', backgroundColor:'green', duration:.2 }, { right:'100px' }]);
</script>
</head>
<body>
<div id="box"></div>
</body>
</html>
Nothing happens...
So, XUI's tween seems to be a work in process. In fact, in the master branch code on GitHub you find:
// queued animations
/* wtf is this?
if (props instanceof Array) {
// animate each passing the next to the last callback to enqueue
props.forEach(function(a){
});
}
*/
So, in short, the array-based tween properties appear busted at the moment. In addition, XUI's tween seems to be a little flakey when dealing with properties that are not currently set on the DOM element. (For example, setting the background-color on a transparent element turns it black...rather than the intended color.)
That said, the single tween and callback work well on previously set properties. So take a look at the following (and excuse the inline css):
<html>
<head>
<script type="text/javascript" src="http://xuijs.com/downloads/xui-2.3.2.min.js"></script>
<script type="text/javascript">
x$.ready(function(){
setTimeout(function(){
x$('#box').tween({'left':'100px', 'background-color':'#339900', duration:2000}, function(){
x$('#box').tween({'left':'500px', duration:2000});
});
}, 500);
});
</script>
</head>
<body style="position:relative;">
<div id="box" style="position:absolute;top:50px;left:500px;width:100px;height:100px;background-color:#fff;border:1px solid #000;">the box</div>
</body>
</html>
Because #box now has a css background-property and left position explicitly set, it is relatively easy to produce an effect similar to the one desired.
One-half second after the page loads, #box should spend 2 seconds moving from left:500px to left:100px while turning the background color from white to green. Then, using the callback, #box moves back to its original position at left:500px--taking another 2 seconds to get back.
Obviously, this does not answer your exact question but for those (like me) who stumble upon this, it provides a workaround for the time being.