您好,我對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