您好,我对Meteor非常陌生,并且正在尝试学习和熟悉Meteor平台。我无法使用聊天功能在我的Meteor应用程序中工作
所以我正在构建一个流星应用{https://github.com/ahadsheriff/SheriffMessenger} 这是基于了另一个例子,我看到{http://chatt.meteor.com/(注:原来的应用程序是使用流星旧版本的构建和一些包没有必要在目前的版本(我的))我克隆示例应用程序的目的是试验流星和应用程序本身,这个想法是(一旦我开始工作)打破代码并研究每个元素,以了解流星是如何工作的。
在我的克隆中,除了两个主要功能在我的版本中不起作用外,一切看起来都很好:聊天/消息传递功能以及查看您正在与哪个用户进行通信并查看他们是否在线的功能。
我已经安装了所有可能的软件包(在Meteor的最新版本中受支持的软件包),我认为我的问题可能是缺少一些基础软件包。
无论如何,我想知道是否有人可以帮助我筛选代码,看看我的问题在哪里,所以我可以让应用程序工作,并重新打破这个代码!
任何帮助表示赞赏!
我上面发布了github链接,为了您的方便,我会在后面发布HTML和Javascript代码。
谢谢,您的帮助将非常感谢!
HTML:
<template name="layout">
<head>
<title>Simple chat</title>
<link href='http://fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'>
</head>
<!-- Wrap all page content here -->
{{> yield}}
</template>
<template name="channel">
<div class="container">
<div class="row">
<div class="col-md-3">
{{> presentation}}
</div>
<div class="col-md-6">
{{> chat}}
</div>
<div class="col-md-3">
{{> participants}}
</div>
</div>
</div>
</template>
<template name="homepage">
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="header">
<a href="/"><h1>Sheriff Messenger</h1></a>
<h2>Chat. Like a Sheriff.</h2>
</div>
<div class="landing">
<form class="form-inline" role="form">
<div class="form-group">
<input type="text" class="form-control" id="channelInput" placeholder="username" maxlength="20" />
<button type="button" id="channelButton" class="btn btn-default">enter</button>
</div>
</form>
<div class="channels">
<ul class="pager">
{{#each channels}}
<li><a href="/c/{{ name }}">{{ name }} - {{ participants.length }} <span class="glyphicon glyphicon-user"></span></a></li>
{{/each}}
</ul>
</div>
</div>
</div>
</div>
</div>
</template>
<template name="presentation">
<a href="/"><h1>Sheriff Messenger</h1></a>
</template>
<template name="participants">
<h3>Participants</h3>
<ul>
{{#each participants}}
<li style="list-style-type: none;"><div class="color-swatch" style="background-color:{{labelClass}};"></div> {{ profile.name }}</li>
{{/each}}
</ul>
<p>Edit your name : </p>
<input type="text" class="form-control" id="nameInput" placeholder="{{name}}" maxlength="40" />
</template>
<template name="chat">
<div class="chat">
<div class="conversation commentArea" id="scroll">
{{#each messages }}
{{#if message}}
<div class="{{authorCss author}}">
{{breaklines message }}<br/>
<i class="author">{{ name }}</i>
</div>
{{else}}
<div class="bubbledLeft">
<i class="author">Sheriff Messenger</i>
</div>
{{/if}}
<script> if (typeof(scrolldown) == "function") { scrolldown(); }</script>
{{/each}}
</div>
<div class="conversationInput">
<input type="text" id="messageInput" class="form-control text" placeholder="Message..." maxlength="300">
</div>
</div>
<script type="text/javascript">
/* Call it everytime ? ....
around 10 times at the first call...
*/
var scrolldown = function() {
console.log("one scrolldown call..."); // reminder to debug...
var elem = document.getElementById('scroll');
elem.scrollTop = elem.scrollHeight;
}
</script>
</template>
的Javascript:
var MeteorUser = function() {
var userId = Meteor.userId();
if (!userId) {
return null;
}
var user = Meteor.users.findOne(userId);
/* if (user !== undefined &&
user.profile !== undefined &&
user.profile.guest) {
return null;
} */
return user;
};
////////// Helpers for in-place editing //////////
// Returns an event map that handles the "escape" and "return" keys and
// "blur" events on a text input (given by selector) and interprets them
// as "ok" or "cancel".
var okCancelEvents = function (selector, callbacks) {
var ok = callbacks.ok || function() {};
var cancel = callbacks.cancel || function() {};
var events = {};
events['keyup '+selector+', keydown '+selector+', focusout '+selector] =
function (evt) {
if (evt.type === "keydown" && evt.which === 27) {
// escape = cancel
cancel.call(this, evt);
} else if (evt.type === "keyup" && evt.which === 13 ||
evt.type === "focusout") {
// blur/return/enter = ok/submit if non-empty
var value = String(evt.target.value || "");
if (value)
ok.call(this, value, evt);
else
cancel.call(this, evt);
}
};
return events;
};
var activateInput = function (input) {
input.focus();
input.select();
};
UI.registerHelper('breaklines', function(text){ // Should call a fonction to sanitaze the html...
var html = "";
if(text) {
html = text.replace(/(\r\n|\n|\r)/gm, '<br>');
}
return Spacebars.SafeString(html);
});
// Not the right way to do it ?!!!
UI.registerHelper('authorCss', function(author){
var cssClass = "bubbledLeft";
if(author === Meteor.userId()) {
cssClass = "bubbledRight";
}
return cssClass;
});
/////////// End Helper ///////
if (Meteor.isClient) {
// Create collection on client
Messages = new Meteor.Collection('messages');
Channels = new Meteor.Collection('channels');
Meteor.startup(function() {
Meteor.loginVisitor(); // Guest Account
//Meteor.insecureUserLogin('Anonymous'); // Test Account
// We take car of the name
Session.setDefault('name', 'Guest');
Session.setDefault('channel', 'yo');
});
//////////// Chat ///////////////
Template.chat.messages = function() {
var messagesCursor = Messages.find({}, {sort:{timestamp:-1}, limit:42});
var messages = messagesCursor.fetch().reverse(); // Should use observechnage to avoid over computation ?
for (var i = messages.length - 1; i >= 0; i--) {
var user = Meteor.users.findOne(messages[i].author);
if (user) {
messages[i].name = user.profile.name;
}
else {
messages[i].name = "Unknown";
}
};
var conversations = [];
var newConversation = messages[0];
for (var i = 0; i <= messages.length - 2; i++) {
var timedelta = messages[i+1].timestamp - messages[i].timestamp;
var sameauthor = (messages[i+1].author === messages[i].author);
if (timedelta <= 30000 && sameauthor) {
newConversation.message = newConversation.message + " \n" + messages[i+1].message;
}
else {
conversations.push(newConversation);
newConversation = messages[i+1];
}
};
conversations.push(newConversation);
// title bar alert
$.titleAlert("New chat message!", {requireBlur: true});
return conversations;
};
Template.chat.events(okCancelEvents(
'#messageInput',
{
ok: function (value, evt) {
Messages.insert({
author: Meteor.userId(),
message: value,
timestamp: (new Date()).getTime(),
channel: Session.get('channel')
});
evt.target.value = "";
}
}
));
//////////// End Chat ///////////////
//////////// Name ///////////////
Template.participants.name = function() {
Meteor.users.findOne(userId)
var user = Meteor.users.findOne(Meteor.userId());
if (user){
Session.set('name', user.profile.name);
}
return Session.get('name');
};
Template.participants.participants = function() {
var labelClass = function(id) { // Certainly not the right way to do it...
if (id === Meteor.userId()) {
return "#428bca";
}
var user = Meteor.users.findOne(id);
if (user) {
if (user.status.online) {
return "#5cb85c";
}
else {
return "#f0ad4e";
}
}
else {
return '#d9534f';
}
};
var participants = Meteor.users.find({}).fetch();
for (var i = participants.length - 1; i >= 0; i--) {
participants[i].labelClass = labelClass(participants[i]._id);
};
return participants;
}
Template.participants.events(okCancelEvents(
'#nameInput',
{
ok: function (value, evt) {
if (value) {
var user = Meteor.users.findOne(Meteor.userId());
if (user){
Meteor.users.update({_id:Meteor.userId()}, {$set:{"profile.name": value}})
}
Session.set('name', value);
}
}
}));
//////////// End Name ///////////////
//////////// Homepage ///////////////
Template.homepage.events(okCancelEvents(
'#channelInput',
{
ok: function (value, evt) {
if (value) {
Session.set('channel', value);
}
}
}));
Template.homepage.channel = function() {
return Session.get('channel');
};
Template.homepage.channels = function() {
return Channels.find({}, {limit:42});
}
Template.homepage.events({
'click #channelButton': function (event, template) {
Router.go('/c/'+Session.get('channel'));
}
});
//////////// END Homepage ///////////
//////////// Routing ///////////////
Router.configure({
layoutTemplate: 'layout'
});
Router.map(function() {
this.route('channel', {
path: '/c/:channel',
template: 'channel',
layoutTemplate: 'layout',
waitOn: function() {
Session.set('channel', this.params.channel);
// Subscribe
Meteor.subscribe("chatroomMessages", this.params.channel);
Meteor.subscribe("channels", this.params.channel);
},
data: function() {
var channel = Channels.findOne({name: this.params.channel});
var participants = [Meteor.userId()]; // default;
if (channel) {
var participants = channel.participants;
}
Meteor.subscribe("users", participants);
}
});
this.route('home', {
path: '/',
template: 'homepage',
layoutTemplate: 'layout',
data: function() {
Meteor.subscribe("channelslist");
}
});
});
//////////// END Routing ///////////
}
if (Meteor.isServer) {
Meteor.startup(function() {
Messages = new Meteor.Collection('messages');
Channels = new Meteor.Collection('channels');
// code to run on server at startup
});
Meteor.publish("channelslist", function() {
return Channels.find({});
});
Meteor.publish("channels", function (channel) {
var id;
if (Channels.findOne({name:channel}) == null) {
id = Channels.insert({
name : channel,
created_timestamp : (new Date()).getTime(),
created_author: this.userId,
participants: [],
message : 0
});
} else {
id = Channels.findOne({name:channel})._id;
}
if (id) {
Channels.update({_id: id}, {$addToSet: { participants: this.userId}});
}
return Channels.find({});
});
Meteor.publish("users", function (listUsers) {
return Meteor.users.find({_id: {$in: listUsers}});
});
Meteor.publish("chatroomMessages", function (channel) {
return Messages.find({channel: channel}, {sort:{timestamp:-1}, limit:42});
});
}
以防万一......这里是CSS:
/* CSS declarations go here */
@media (min-width: 1200px) {
[class*="span"] {
margin-left: 20px; /* correction ??? */
}
}
body {
background-color: #e7e7e7;
}
.chat {
height: 100vh; /* What is that ? */
background-color: #fff;
-webkit-box-shadow: 0px 3px 5px 0px rgba(0, 0, 0, 0.61);
-moz-box-shadow: 0px 3px 5px 0px rgba(0, 0, 0, 0.61);
box-shadow: 0px 3px 5px 0px rgba(0, 0, 0, 0.61);
}
.conversation {
height: calc(100% - 50px); /* Use preprocessing to get a fixed .conversationInput-height */
overflow-x:hidden;
overflow-y: auto;
}
.conversationInput {
background-color: #ccf;
height: 50px;
bottom: 0;
}
/* CSS chat 'stolen' from http://jsfiddle.net/anuradhabajpai/x8C8S/10/ */
.commentArea {
font: 14px Arial;
padding: 0 10px 0px;
}
.bubbledLeft,.bubbledRight {
margin-top: 10px;
margin-bottom: 10px;
padding: 5px 9px;
max-width: 80%;
clear: both;
position: relative;
}
.bubbledLeft{
float: left;
margin-right: auto;
-webkit-border-radius: 8px 8px 8px 0px;
-moz-border-radius: 8px 8px 8px 0px;
-o-border-radius: 8px 8px 8px 0px;
-ms-border-radius: 8px 8px 8px 0px;
border-radius: 8px 8px 8px 0px;
background-color: #65B045;
color: #ffffff;
}
.bubbledLeft:before {
border-bottom: 10px solid #65B045;
border-left: 9px solid rgba(0, 0, 0, 0);
position: absolute;
bottom: 0;
left: -8px;
content: "";
}
.bubbledRight{
float: right;
margin-left: auto;
text-align: right;
-webkit-border-radius: 8px 8px 0px 8px;
-moz-border-radius: 8px 8px 0px 8px;
-o-border-radius: 8px 8px 0px 8px;
-ms-border-radius: 8px 8px 0px 8px;
border-radius: 8px 8px 0px 8px;
background-color: #07D;
color: white;
}
.bubbledRight:before {
border-bottom: 9px solid #07D;
border-right: 9px solid rgba(0, 0, 0, 0);
position: absolute;
bottom: 0;
right: -8px;
content: "";
}
.author {
opacity: .5;
font-size: .9em;
}
/* END CSS Chat */
#messageInput {
width: 100%;
padding: 0px;
padding-left: 16px;
height: 100%;
border-bottom: 0;
border-radius: 0;
}
.color-swatch {
width: 12px;
height: 12px;
display: inline-block;
border-radius: 50%;
}
body {
font-family: 'Roboto', sans-serif;
}
.landing {
padding-top: 150px;
text-align: center;
}
.channels {
padding: 10px 10px 10px 10px;
}
h1 {
text-decoration: none;
text-decoration-color: none;
color: #333;
}
.header h1 {
text-align: center;
}
而且这里是包的列表我使用:
meteor-platform
autopublish
insecure
mrt:moment
ostrio:user-status
accounts-base
accounts-password
artwells:accounts-guest
mizzao:accounts-testing
fortawesome:fontawesome
iron:router
twbs:bootstrap
meteorhacks:fast-render
peerlibrary:related
standard-app-packages
再次感谢您的帮助!
谢谢!您的解决方案在让参与者出现的过程中起作用。但是,这些消息仍然不会发送,并且您无法看到哪些参与者在线:( – 2015-03-02 15:42:57
我已经指出了另外2个错误,请仔细阅读您的代码,并且现在应该更近一些。还要尝试使用浏览器调试工具来检查属性,以便找到问题出在哪里 – Salketer 2015-03-02 15:53:20
谢谢你的帮助!我一直在尝试,但我仍然无法让消息工作,我会继续寻找,但截至目前为止,我不知道我的信息是怎么回事。 – 2015-03-02 16:13:17