I am making a Chatroom using nodejs. I am using express, socket.io and http for this purpose. I am looking for options to do file sharing over the http server. The preferred file formats are image files(.jpg or .png) and text files. But I am not able to do it. I tried using the input tag of html but it didn't upload any files to the server.
This is my server side code (server.js)
var express = require("express")
, app = express()
, http = require("http").createServer(app)
, bodyParser = require("body-parser")
, io = require("socket.io").listen(app.listen(3000))
, _ = require("underscore");
const file = require('express-fileupload');
app.use(file());
var participants = [];
app.set("ipaddr", "127.0.0.1");
app.set("port", 8080);
app.set("views", __dirname + "/views");
app.set("view engine", "jade");
app.use(express.static("public", __dirname + "/public"));
app.use(bodyParser.json());
app.get("/", function(request, response) {
response.render("index");
});
app.post("/message", function(request, response) {
var message = request.body.message;
if(_.isUndefined(message) || _.isEmpty(message.trim())) {
return response.json(400, {error: "Message is invalid"});
}
var name = request.body.name;
io.sockets.emit("incomingMessage", {message: message, name: name});
response.json(200, {message: "Message received"});
});
io.on("connection", function(socket){
socket.on("newUser", function(data) {
participants.push({id: data.id, name: data.name});
io.sockets.emit("newConnection", {participants: participants});
});
socket.on("nameChange", function(data) {
_.findWhere(participants, {id: socket.id}).name = data.name;
io.sockets.emit("nameChanged", {id: data.id, name: data.name});
});
socket.on("disconnect", function(data) {
participants = _.without(participants,_.findWhere(participants, {id: socket.id}));
io.sockets.emit("userDisconnected", {id: socket.id, sender:"system"});
});
});
http.listen(app.get("port"), app.get("ipaddr"), function() {
console.log("Server ready. IP address: " + app.get("ipaddr") + " ..port:" + app.get("port"));
});
This is the client side code (index.js)
function init() {
var url = document.domain;
var socket = io.connect(url);
var sId = '';
function updateParticipants(mem) {
$('#participants').html('');
for (var i = 0; i < mem.length; i++) {
$('#participants').append('<span id = ' + mem[i].id + '>' +
mem[i].name + ' ' + (mem[i].id === sId ? '(You)' : '') + '<br> </span>');
}
}
socket.on('connect', function () {
sId = socket.io.engine.id;
console.log('Connected ' + sId);
socket.emit('newUser', {id: sId, name: $('#name').val()});
});
socket.on('newConnection', function (data) {
updateParticipants(data.participants);
$('#messages').prepend('<br> New user joined <hr>');
});
socket.on('userDisconnected', function(data) {
$('#' + data.id).remove();
});
socket.on('nameChanged', function (data) {
$('#' + data.id).html(data.name + ' ' + (data.id === sId ? '(You)' : '') + '<br> ');
});
socket.on('incomingMessage', function (data) {
var message = data.message;
var name = data.name;
$('#messages').prepend('<b>' + name + '</b><br>' + message + '<h6 style = "color: green; font-size: 11px">'+new Date().toString()+'</h6>'+'<hr>');
});
socket.on('error', function (reason) {
console.log('Unable to connect to server', reason);
});
function sendMsg() {
var outgoingMessage = $('#outgoingMessage').val();
var name = $('#name').val();
$.ajax({
url: '/message',
type: 'POST',
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify({message: outgoingMessage, name: name})
});
}
function sendAttachment(){
var attachment=$('#attachment').val();
var name = $('#name').val();
$.ajax({
url: '/message',
type: 'POST',
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify({message: outgoingMessage, name: name})
});
}
function msgKeyDown(event) {
if (event.which == 13) {
event.preventDefault();
if ($('#outgoingMessage').val().trim().length <= 0) {
return;
}
sendMsg();
$('#outgoingMessage').val('');
var att = $('#attachment').val();
}
}
function msgKeyUp() {
var outgoingMessageValue = $('#outgoingMessage').val();
$('#send').attr('disabled', (outgoingMessageValue.trim()).length > 0 ? false : true);
}
function focusName() {
var name = $('#name').val();
socket.emit('nameChange', {id: sId, name: name});
}
$('#outgoingMessage').on('keydown', msgKeyDown);
$('#outgoingMessage').on('keyup', msgKeyUp);
$('#name').on('focusout', focusName);
$('#send').on('click', sendMsg);
$('#sendFile').on('click',sendAttachment);
}
$(document).on('ready', init);
And for the front-end I made a Jade file (index.jade)
doctype html
html
head
link(rel='stylesheet', href='http://fonts.googleapis.com/css?family=Open+Sans')
link(rel='stylesheet', href='/css/style.css')
script(src='//code.jquery.com/jquery-1.11.0.min.js')
script(src='/socket.io/socket.io.js')
script(src='/js/index.js')
title Chatroom
body
h1(style="color: red; text-align: center") Live ChatRoom
div(style="color: red;")
div.inlineBlock
span Your name:
input(type="text", value=" ", style="background-color: blue; color: orange; width: 300px; height:40px; font-size: 35px")#name
br
form#messageForm
textarea(rows="7", cols="60", placeholder="Say something and press enter(maximum 300 characters)",maxlength=300, style ="background-color: black;color: yellow; font-size: 20px")#outgoingMessage
br
input(type="button", value="SEND", disabled=true, style="backround-color: purple; color:black; ")#send
div.inlineBlock.topAligned
b Participants
br
div(style = "color: gold")#participants
div(style = "color: Yellow")#messages
Any suggestions how I can do file sharing in the code?
PS The 'express-fileupload' in server.js was a npm package i tried using for file sharing which didn't work.
You are right looking at:
<input type="file" id="input>
Here is an example code, that will send an "image" event via WebSockets after a file has been selected. The logic for handling "image" events should be similar to your "incomingMessage" but I recommend to separate them.
document.getElementById("input").addEventListener("change", function (event) {
// Prepeare file reader
var file = event.target.files[0];
var fileReader = new FileReader();
fileReader.onloadend = function (event) {
var image = event.target.result
// Send an image event to the socket
socket.emit("image", image);
};
// Read file
fileReader.readAsDataURL(file);
})
If you want to display the image coming from a WebSocket, you can simply set the "src" attribute on an image element:
<img src="" id="output />
And the JavaScript that listens for the WebSocket event:
socket.on("image", function (image) {
output.src = image;
});
You can find a complete example for sending images through WebSockets here: https://medium.com/#getflourish/from-mobile-to-desktop-cross-device-communication-using-websockets-f9c48f669c8
Related
I am newbie to Vue.js.I am trying to export some data to excel file but i don't want all of the data columns to be exported. Rather i need to select few columns.I tried using map function but no luck.Any help really appriciated.Here is my code
<button class="btn_form" #click="exportTo">Export to Excel</button>
exportTo() {
this.form.exportExcel = true
axios.post(route('report'), this.form,
{
responseType: 'blob',
})
.then((response) => {
console.log(response)
const result = response.data.data.map((item) => {
return {
Name: item.firstname + ' ' + item.middlename+ ' ' + item.lastname,
Address: item.table2.res_address+ ' ,' + item.table2.res_city+ ' ,' + item.table2.res_state+ ' ,' + item.table2.res_pincode,
Mobile : item.phone,
Email : item.email,
Place : item.table2.place,
Gender : item.gender,
DOB : item.birthdate
};
});
console.log(result);
const url = window.URL.createObjectURL(new Blob([result]));
const link = document.createElement('a');
link.href = url;
var datetime = new Date().getTime()
link.setAttribute('download',datetime+'reportdata.xlsx');
document.body.appendChild(link);
link.click();
this.form.exportExcel = false
})
.catch((error) => {
this.form= []
})
},
The response data is something like this
{
"data":{
"current_page":1,
"data":[
{
"id":17198,
"f_id":003,
"firstname":"ABC",
"middlename":"M",
"lastname":"XYZ",
"phone":"1234567899",
"email":"xyz#gmail.com",
"faxno":"",
"company_url":"",
"birthdate":"2012-03-06",
"gender":"FEMALE",
"mobile":"1234567899",
"created_at":"2022-01-28T18:05:11.000000Z",
"updated_at":"2022-07-21T11:33:14.000000Z",
"table2":{
"id":18845,
"f_id":003,
"vip_no":950,
"place":"Mumbai",
"res_address":"Q110 Madhav Heights\r\n Goregaon West",
"res_city":"Mumbai",
"res_state":"Goa",
"res_country":"",
"res_pincode":"4000",
"alt_address":"Test address223",
"alt_city":"Testcity",
"alt_state":"Kerala",
"alt_country":"",
"alt_pincode":"4000",
"f_email":"cde123#gmail.com",
"created_at":"2022-04-12T11:41:11.000000Z",
"updated_at":"2022-04-12T11:41:11.000000Z"
}
},
As you see in the code I am trying to export only name,address,mobile,email. Actually my response data is larger than what I have put.So direct export to excel doesn't work. It gives me "Excel cannot open the file because of the file format or file extension is invalid".
I'm converting an old LAMP stack project to use Node/Express/MongoDB instead of PHP/Laravel/MySQL. I built out my routes the same way I did in Laravel and have tested the routes I've built using Postman. Every route works as it should through testing in Postman.
However, when I try to use these routes in the display.js file that I wrote, the only route that works is GET /players. I am looking for some insight on these routes and the display file I'm using.
When I click the edit button, my GET /player/:id route grabs the correct information (status code 200 and preview shows JSON object) but will not populate the fields in my form.
When I click the delete button, I get a 404 status code with a response of "Cannot GET /players/123/delete". How do I adjust my display code to use DELETE instead of GET? (I believe I can refactor my all of my routes to just /players/:id using the correct http request method if I can figure out how to pass the request method in the display.js code).
When I try to submit a new record, I get a 400 status code with validation error saying Path age is required. It's actually the same error for each field name, so I assume that I'm not passing the values from the field into the JSON object correctly.
I haven't been able to test patch, but believe it should be remedied through fixing DELETE /players/:id and GET /players/:id.
Any help is appreciated. Code is below for display and server js files.
display.js
// this is the base url to which all your requests will be made
var baseURL = window.location.origin;
$(document).ready(function(){
// $.ajaxSetup({
// headers: {
// 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
// }
// });
$('#table').click(function(event) { // generates the table
// change the url parameters based on your API here
// Using an JQuery AJAX GET request to get data form the server
$.getJSON(baseURL+'/players', function(data) {
generateTable(data, $('#container'));
});
});
$('#form').click(function(event) {
// creating an empty form
generateForm(null, $('#container'));
});
// Handle table click event for delete
$('#container').on('click', '.delete', function(event) {
var id = $(this).val();
// change the url parameters based on your API here
// remember to create delete functionality on the server side (Model and Controller)
// Using an JQuery AJAX GET request to get data form the server
$.getJSON(baseURL+"/players/"+id+"/delete", function(data) {
//Generate table again after delete
//change the url based on your API parameters here
// Using an JQuery AJAX GET request to get data from the server
$.getJSON(baseURL+'/players', function(data) {
generateTable(data, $('#container'));
});
});
});
// Handle form submit event for both update & create
// if the ID_FIELD is present the server would update the database otherwise the server would create a record in the database
$('#container').on('submit', '#my-form', function(event) {
var id = $('#id').val();
console.log(id);
if (id != "") {
event.preventDefault();
submitForm(baseURL+"/players/"+id+"/edit", $(this));
} else {
event.preventDefault();
submitForm(baseURL+"/player", $(this));
}
});
// Handle table click event for edit
// generates form with prefilled values
$('#container').on('click', '.edit', function(event) {
// getting id to make the AJAX request
var id = $(this).val();
// change the url parameters based on your API here
// Using an JQuery AJAX GET request to get data form the server
$.getJSON(baseURL+'/players/'+id, function(data) {
generateForm(data, $('#container'));
});
});
// function to generate table
function generateTable(data, target) {
clearContainer(target);
//Change the table according to your data
var tableHtml = '<table><thead><tr><th>Name</th><th>Age</th><th>Position</th><th>Team</th><th>Delete</th><th>Edit</th></tr></thead>';
$.each(data, function(index, val) {
tableHtml += '<tr><td>'+val.playername+'</td><td>'+val.age+'</td><td>'+val.position+'</td><td>'+val.team+'</td><td><button class="delete" value="'+val._id+'">Delete</button></td><td><button class="edit" value="'+val._id+'">Edit</button></td></tr>';
});
tableHtml += '</table>';
$(target).append(tableHtml);
}
// function to generate form
function generateForm(data, target){
clearContainer(target);
//Change form according to your fields
$(target).append('<form id="my-form"></form>');
var innerForm = '<fieldset><legend>Player Form</legend><p><label>Player Name: </label>'+'<input type="hidden" name="id" id="id"/>'+'<input type="text" name="playername" id="playername" /></p>' + '<p><label>Age: </label><input type="text" name="age" id="age" /></p>'+ '<p><label>Hometown: </label><input type="text" name="city" id="city" />'+ ' ' + '<input type="text" name="country" id="country" /></p>' + '<p><label>Gender: </label><input type="text" name="gender" id="gender" /></p>'+ '<p><label>Handedness: </label><input type="text" name="handedness" id="handedness" /></p>'+ '<p><label>Broom: </label><input type="text" name="broom" id="broom" /></p>'+ '<p><label>Position: </label><input type="text" name="position" id="position" /></p>'+ '<p><label>Team: </label><input type="text" name="team" id="team" /></p>'+ '<p><label>Favorite Color: </label><input type="text" name="favoritecolor" id="favoritecolor" /></p>'+ '<p><label>Headshot: </label><input type="text" name="headshot" id="Headshot" /></p>'+ '<input type="submit"/>';
$('#my-form').append(innerForm);
//Change values according to your data
if(data != null){
$.each(data, function(index, val) {
$('#id').val(val._id);
$('#playername').val(val.playername);
$('#age').val(val.age);
$('#city').val(val.city);
$('#country').val(val.country);
$('#gender').val(val.gender);
$('#handedness').val(val.handedness);
$('#broom').val(val.broom);
$('#position').val(val.position);
$('#team').val(val.team);
$('#favoritecolor').val(val.favoritecolor);
$('#Headshot').val(val.headshot);
});
}
}
function submitForm(url, form){
$.post(url, form.serialize(), function(data) {
showNotification(data, $('#notification'));
});
}
function showNotification(data, target){
clearContainer(target);
target.append('<p>'+data+'</p>');
}
function clearContainer(container){
container.html('');
}
});
server.js
const _ = require('lodash');
const {ObjectID} = require('mongodb');
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
var {mongoose} = require('./db/mongoose');
var {Player} = require('./models/player');
var app = express();
const port = process.env.PORT || 3000;
app.use(express.static(__dirname+'./../public'));
app.use(bodyParser.json());
app.get('/', (req, res) => {
res.sendFile('index.html');
});
app.post('/player', (req, res) => {
var player = new Player({
playername: req.body.playername,
age: req.body.age,
city: req.body.city,
country: req.body.country,
gender: req.body.gender,
handedness: req.body.handedness,
broom: req.body.broom,
position: req.body.position,
team: req.body.team,
favoritecolor: req.body.favoritecolor,
headshot: req.body.headshot
});
player.save().then((doc) => {
res.send(doc);
}, (e) => {
res.status(400).send(e);
});
});
app.get('/players', (req, res) => {
Player.find().then((players) => {
res.send(players);
}, (e) => {
res.status(400).send(e);
});
});
app.get('/players/:id', (req, res) => {
var id = req.params.id;
if (!ObjectID.isValid(id)) {
return res.status(404).send();
}
Player.findById(id).then((player) => {
if (player) {
res.send(player);
} else {
return res.status(404).send();
}
}).catch((e) => {
res.status(400).send();
});
});
app.delete('/players/:id/delete', (req, res) => {
var id = req.params.id;
if (!ObjectID.isValid(id)) {
return res.status(404).send();
}
Player.findByIdAndRemove(id).then((player) => {
if (player) {
res.send(player);
} else {
return res.status(404).send();
}
}).catch((e) => {
res.status(400).send();
});
});
app.patch('/players/:id/edit', (req, res) => {
var id = req.params.id;
var body = _.pick(req.body, ['playername', 'age', 'city', 'country', 'gender', 'handedness', 'broom', 'position', 'team', 'favoritecolor', 'headshot']);
if (!ObjectID.isValid(id)) {
return res.status(404).send();
}
Player.findByIdAndUpdate(id, {$set: body}, {new: true}).then((player) => {
if (!player) {
return res.status(404).send();
} else {
res.send(player);
}
}).catch((e) => {
res.status(400).send();
})
});
app.listen(port, () => {
console.log(`Started on port ${port}`);
});
module.exports = {app};
When I click the delete button, I get a 404 status code with a response of "Cannot GET /players/123/delete". How do I adjust my display code to use DELETE instead of GET? (I believe I can refactor my all of my routes to just /players/:id using the correct http request method if I can figure out how to pass the request method in the display.js code).
This is because your app has app.delete('/players/:id/delete') and not app.get('/players/:id/delete'). However, your server side code shouldn't change much, just one tweak:
If you have an app.delete() then really no need to have the verb delete at the end of the resource.
Also you need to make the request using the HTTP Method DELETE instead of making a GET in display.js. Just make the DELETE request using $.ajax() with type set to 'DELETE'
When I click the edit button, my GET /player/:id route grabs the correct information (status code 200 and preview shows JSON object) but will not populate the fields in my form.
This is because your implementation of $.each() assumes data will always be an Array and not ever and object, however, your generateForm() is passing in a Player object. Change your $.each() to do type checking for array handling and object handling. See below changes.
When I try to submit a new record, I get a 400 status code with validation error saying Path age is required. It's actually the same error for each field name, so I assume that I'm not passing the values from the field into the JSON object correctly.
If you make the above change to generateForm() it should fix this.
Just take the below snippets and replace those sections within your app, it should work.
server.js
app.delete('/players/:id', (req, res) => {
var id = req.params.id;
if (!ObjectID.isValid(id)) {
return res.status(404).send();
}
return Player.findByIdAndRemove(id).then((player) => {
if (player) {
res.status(200).json(player);
} else {
return res.status(404).send();
}
}).catch((e) => {
res.status(400).send();
});
});
app.patch('/players/:id', (req, res) => {
var id = req.params.id;
var body = _.pick(req.body, ['playername', 'age', 'city', 'country', 'gender', 'handedness', 'broom', 'position', 'team', 'favoritecolor', 'headshot']);
if (!ObjectID.isValid(id)) {
return res.status(404).send();
}
Player.findByIdAndUpdate(id, {$set: body}, {new: true}).then((player) => {
if (!player) {
return res.status(404).send();
} else {
res.status(200).json(player);
}
}).catch((e) => {
res.status(400).send();
})
});
app.post('/players', (req, res) => {
var player = new Player({
playername: req.body.playername,
age: req.body.age,
city: req.body.city,
country: req.body.country,
gender: req.body.gender,
handedness: req.body.handedness,
broom: req.body.broom,
position: req.body.position,
team: req.body.team,
favoritecolor: req.body.favoritecolor,
headshot: req.body.headshot
});
return player.save().then((doc) => {
return res.status(200).json(doc);
}, (e) => {a
return res.status(400).send(e);
});
});
display.js
// Handle form submit event for both update & create
// if the ID_FIELD is present the server would update the database otherwise the server would create a record in the database
$('#container').on('submit', '#my-form', function(event) {
var id = $('#id').val();
let formData = {};
$.each($('#myForm').serializeArray(), function(_, kv) {
if (formData.hasOwnProperty(kv.name)) {
formData[kv.name] = $.makeArray(formData[kv.name]);
formData[kv.name].push(kv.value);
}
else {
formData[kv.name] = kv.value;
}
});
console.log(id);
if (id != "") {
event.preventDefault();
$.ajax({
url: baseURL + '/players/' + id,
type: 'PATCH',
success: function(edited) {
// Handle returned edited player
}
})
} else {
event.preventDefault();
$.ajax({
url: baseURL + '/players',
type: 'POST',
success: function(created) {
// Handle created player
}
})
}
});
// Handle table click event for delete
$('#container').on('click', '.delete', function(event) {
var id = $(this).val();
// change the url parameters based on your API here
// remember to create delete functionality on the server side (Model and Controller)
// Using an JQuery AJAX GET request to get data form the server
$.ajax({
url: baseURL + '/players/' + id,
type: 'DELETE',
success: function(data) {
//Generate table again after delete
//change the url based on your API parameters here
// Using an JQuery AJAX GET request to get data from the server
$.getJSON(baseURL+'/players', function(data) {
generateTable(data, $('#container'));
});
}
});
});
// function to generate form
function generateForm(data, target){
clearContainer(target);
//Change form according to your fields
$(target).append('<form id="my-form"></form>');
var innerForm = '<fieldset><legend>Player Form</legend><p><label>Player Name: </label>'+'<input type="hidden" name="id" id="id"/>'+'<input type="text" name="playername" id="playername" /></p>' + '<p><label>Age: </label><input type="text" name="age" id="age" /></p>'+ '<p><label>Hometown: </label><input type="text" name="city" id="city" />'+ ' ' + '<input type="text" name="country" id="country" /></p>' + '<p><label>Gender: </label><input type="text" name="gender" id="gender" /></p>'+ '<p><label>Handedness: </label><input type="text" name="handedness" id="handedness" /></p>'+ '<p><label>Broom: </label><input type="text" name="broom" id="broom" /></p>'+ '<p><label>Position: </label><input type="text" name="position" id="position" /></p>'+ '<p><label>Team: </label><input type="text" name="team" id="team" /></p>'+ '<p><label>Favorite Color: </label><input type="text" name="favoritecolor" id="favoritecolor" /></p>'+ '<p><label>Headshot: </label><input type="text" name="headshot" id="Headshot" /></p>'+ '<input type="submit"/>';
$('#my-form').append(innerForm);
//Change values according to your data
if(data instanceof Array){
$.each(data, function(index, val) {
$('#id').val(val._id);
$('#playername').val(val.playername);
$('#age').val(val.age);
$('#city').val(val.city);
$('#country').val(val.country);
$('#gender').val(val.gender);
$('#handedness').val(val.handedness);
$('#broom').val(val.broom);
$('#position').val(val.position);
$('#team').val(val.team);
$('#favoritecolor').val(val.favoritecolor);
$('#Headshot').val(val.headshot);
});
}
else if (typeof data === 'object') {
$.each(data, function(key, value) => {
$('#' + key).val(value);
});
}
}
Try res.json(player); instead of res.send(player); in order to send the data in JSON format.
Also, instead of $.post(url, form.serialize(), function(data) {try the code from this answer in order to send the data in JSON format.
I have a problem with running VueJS on mobile devices. I created a weather prediction app on copepen.io
Here is the link for the project:
http://codepen.io/techcater/pen/xOZmgv
HTML code:
<div class="container-fluid text-center">
<h1>Your Local Weather</h1>
<p>
{{location}}
</p>
<p>
{{temperature}}
<a #click="changeDegree">{{degree}}</a>
</p>
<p>
{{weather | capitalize}}
</p>
<img :src="iconURL" alt="" />
<br>
by Dale Nguyen
<!-- <pre>{{$data | json}}</pre> -->
</div>
JS code:
new Vue({
el: '.container-fluid',
data: {
location: "",
temperature: "",
degree: "C",
weather: "",
iconURL: ""
},
created: function(){
this.getWeather();
},
methods: {
getWeather: function(){
var that = this;
this.$http.get("http://ipinfo.io").then((response) => {
console.log(response.data);
that.location = response.data.city + ", " + response.data.country;
// Get weather informaiton
var api = 'ebd4d312f85a230d5dc1db91e20c2ace';
var city = response.data.city;
var url = "http://api.openweathermap.org/data/2.5/weather?q={CITY}&APPID={APIKEY}&units=metric";
url = url.replace("{CITY}",city);
url = url.replace("{APIKEY}", api);
that.$http.post(url,{dataType: 'jsonp'},{
headers : {
'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8'
}}).then((response) => {
console.log(response.data);
that.temperature = response.data.main.temp;
that.weather = response.data.weather[0]['description'];
that.iconURL = "http://openweathermap.org/img/w/" + response.data.weather[0]['icon'] + ".png";
}, (response) => {
// error callback
});
}, (response) => {
console.log(response.data);
});
},
changeDegree: function() {
if(this.degree == "C"){
this.degree = "F";
this.temperature = Math.round((this.temperature*9/5 + 32)*100)/100;
}else {
this.degree = "C";
this.temperature = Math.round(((this.temperature - 32)*5 /9)* 100)/100;
}
}
}
})
It works well on my laptop but not on mobile. At first, I thought that it is because of Codepen. It may cause something when running through the site. However, when I created a project on my website, it also doesn't work.
Can you help to find the issue? Thanks,
Your code seems to be working well, except that on codepen it gives me error XMLHttpRequest cannot load http://ipinfo.io/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://s.codepen.io' is therefore not allowed access..
You can put your domain name on headers options to enable cross-origin, here is example:
this.$http.get('http://ipinfo.io', {
'headers': {
'Origin': 'http://yourdomain.com'
}
})
See example: http://bozue.com/weather.html
I also noticed you put vue.min.js and vue-resource.js scripts in wrong order that might trigger some error, vue.min.js should be on the first place.
I found a solution for this. I works on my mobile now. I believe that I will work on other browses too. The problem is that some browsers doesn't recognize the operation ">", so I changed it.
Here is the new code:
getWeather: function(){
var that = this;
this.$http.get('http://ipinfo.io', {'headers': {
'Origin': 'http://yourdomain.com'}
}).then(function(response) {
console.log(response.data);
that.location = response.data.city + ", " + response.data.country;
// Get weather informaiton
var api = 'ebd4d312f85a230d5dc1db91e20c2ace';
var city = response.data.city;
var url = "https://crossorigin.me/http://api.openweathermap.org/data/2.5/weather?q={CITY}&APPID={APIKEY}&units=metric";
url = url.replace("{CITY}",city);
url = url.replace("{APIKEY}", api);
that.$http.post(url,{dataType: 'jsonp'},{
headers : {
'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8'
}}).then(function(response) {
console.log(response.data);
that.temperature = response.data.main.temp;
that.weather = response.data.weather[0]['description'];
that.iconURL = "http://openweathermap.org/img/w/" + response.data.weather[0]['icon'] + ".png";
}).then(function(){
// error callback
});
}).then(function(){
console.log(response.data);
});
},
I'm trying to implement something with jQuery and Vue.js:
And here is my script part:
<script>
function initVM(result) {
// alert(result.num)
var vm2 = new Vue({
el: '#vm2',
data: {
// ③bind one item of the result as example
rrr: result.num
}
});
$('#vm2').show();
}
$(function() {
var vm = new Vue({
el: '#vm',
data: {
content: ''
},
methods: {
submit: function(event) {
event.preventDefault();
var
$form = $('#vm'),
content = this.content.trim();
// ①post textarea content to backend
$form.postJSON('/api/parse', {
content: content
}, function(err, result) {
if (err) {
$form.showFormError(err);
}
else {
// ②receive a result dictionary
$('#vm').hide();
initVM(result);
}
});
}
}
});
});
</script>
Here is my html part:
<html>
<form id="vm", v-on="submit: submit">
<textarea v-model="content" name="content"></textarea>
<button type="submit">Have a try!</button>
</form>
<div id="vm2" style="diplay:none;">
<!-- ④show the result-->
The result:
{{ rrr }}
</div>
</html>
Here is the definition of postJSON
<script>
// ...
postJSON: function (url, data, callback) {
if (arguments.length===2) {
callback = data;
data = {};
}
return this.each(function () {
var $form = $(this);
$form.showFormError();
$form.showFormLoading(true);
_httpJSON('POST', url, data, function (err, r) {
if (err) {
$form.showFormError(err);
$form.showFormLoading(false);
}
callback && callback(err, r);
});
});
// ...
// _httpJSON
function _httpJSON(method, url, data, callback) {
var opt = {
type: method,
dataType: 'json'
};
if (method==='GET') {
opt.url = url + '?' + data;
}
if (method==='POST') {
opt.url = url;
opt.data = JSON.stringify(data || {});
opt.contentType = 'application/json';
}
$.ajax(opt).done(function (r) {
if (r && r.error) {
return callback(r);
}
return callback(null, r);
}).fail(function (jqXHR, textStatus) {
return callback({'error': 'http_bad_response', 'data': '' + jqXHR.status, 'message': 'something wrong! (HTTP ' + jqXHR.status + ')'});
});
}
</script>
The process can be described as:
Post the content to backend
Receive the result and hide the form
Create a new Vue with the result
Show the result in a div which is binding with the new Vue instance
Actually, I do receive the result successfully, which is proved by the alert(result.num) statement, but nothing find in vm2's div except The result:
Where is the problem? Or please be free to teach me a simpler approach if there is, because I don't think what I am using is a good one.
Here's questioner.
Finally I found where is the problem.
The problem lays in Mustache: {{ }}
I use jinja2, a template engine for Python and Vue.js, a MVVM frontend framework. Both of them use {{ }} as delimiters.
So if anyone got trapped in the same situation with me, which I don't think there will be, please:
app.jinja_env.variable_start_string = '{{ '
app.jinja_env.variable_end_string = ' }}' # change jinjia2 config
OR
Vue.config.delimiters = ['${', '}'] # change vue config
I'm trying to use JEditable plugin in my Symfony2 application. PYS entity is a a films and TV shows entity; then I've got Usuario and Critica entities. I want to manage the user's critics with the plugin. I've analyzed more and more examples, but I can not get it to work. The value (in this case the title of critic) is update in the template but not in the db; when I refresh the browser the old value appears.
THE ERROR:
This is my JS:
$('.edit').editable(function(value, settings) {
var data = {};
data[this.id] = value;
console.log(path);
console.log(data);
$.post(path, data);
return(value);
}, {
indicator : 'Saving...',
tooltip : 'Click to edit...'
});
This is the route:
critica_ajax:
locales: { es: "/gestion-critica/{pysStr}/", en: "/manage-critic/{pysStr}/" }
defaults: { _controller: UsuarioBundle:Default:gestionarCritica }
This is the controller:
public function gestionarCriticaAction($pysStr)
{
$em = $this->getDoctrine()->getManager();
$pys = $em->getRepository('PYSBundle:Pys')->findPys($pysStr);
$usuario = $this->get('security.context')->getToken()->getUser();
$critica = $em->getRepository('UsuarioBundle:Usuario')->findCritica($usuario, $pys);
if(!$critica)
{
$critica = new Critica($usuario, $pys);
}
$criTitulo = $this->request->get('value');
$critica->setCriTitulo($criTitulo);
$critica->setCriContenido($criContenido);
$critica->setCriFecha(new \DateTime("now"));
$em->persist($critica);
$em->flush();
return new Response($criTitulo);
}
The Twig template:
<h2 class="edit">{{ critica.criTitulo }}</h2>
<script>
var path = "{{ path('critica_ajax', { 'pysStr': pelicula.pysStr}) }}";
</script>
EDIT (The Symfony's return)
Notice: Undefined property: Filmboot\UsuarioBundle\Controller\DefaultController::$request
in C:\Programming\xampp\htdocs\filmboot\src\Filmboot\UsuarioBundle\Controller\DefaultController.php line 236
THIS IS THE LINE 236: $criTitulo = $this->request->get('value');
at ErrorHandler ->handle ('8', 'Undefined property: Filmboot\UsuarioBundle\Controller\DefaultController::$request', 'C:\Programming\xampp\htdocs\filmboot\src\Filmboot\UsuarioBundle\Controller\DefaultController.php', '236', array('pysStr' => 'machete', 'em' => object(EntityManager), 'pys' => object(Pys), 'usuario' => object(Usuario), 'critica' => object(Critica)))
in C:\Programming\xampp\htdocs\filmboot\src\Filmboot\UsuarioBundle\Controller\DefaultController.php at line 236 +
at DefaultController ->gestionarCriticaAction ('machete')
at call_user_func_array (array(object(DefaultController), 'gestionarCriticaAction'), array('machete'))
in C:\Programming\xampp\htdocs\filmboot\app\bootstrap.php.cache at line 1003 +
at HttpKernel ->handleRaw (object(Request), '1')
in C:\Programming\xampp\htdocs\filmboot\app\bootstrap.php.cache at line 977 +
at HttpKernel ->handle (object(Request), '1', true)
in C:\Programming\xampp\htdocs\filmboot\app\bootstrap.php.cache at line 1103 +
at ContainerAwareHttpKernel ->handle (object(Request), '1', true)
in C:\Programming\xampp\htdocs\filmboot\app\bootstrap.php.cache at line 413 +
at Kernel ->handle (object(Request))
in C:\Programming\xampp\htdocs\filmboot\web\app_dev.php at line 26 +
You need to get the request like this :
$request = $this->getRequest();
instead of
$request = $this->request;
the request is returned using a method its not a class property