I'm new to Meteor and building a simple app to learn the framework. The app I'm building let's you place words on an image of a kitten.
我是Meteor的新手,并构建了一个简单的应用程序来学习框架。我正在构建的应用程序让你在小猫的图像上放置文字。
The desired behavior is this:
期望的行为是这样的:
A user clicks anywhere on the kitten, and a contenteditable element appears letting the user enter text. Clicking outside of the element saves the element, and it remains in place.
用户点击小猫的任何位置,并出现一个让用户输入文本的可信元素。单击元素外部将保存元素,并保持原位。
The problem I'm running into:
我遇到的问题:
If I have two browser windows opened with the app, and I click on one kitten in one window, an empty field appears in both windows. Ideally, the empty field would appear only on the window I clicked on. Once a word is saved, then in should be visible in both windows.
如果我在应用程序中打开了两个浏览器窗口,并在一个窗口中单击一只小猫,则两个窗口中都会显示一个空白字段。理想情况下,空字段仅出现在我单击的窗口上。保存一个单词后,应该在两个窗口中都可以看到。
My question:
我的问题:
Is there a way to insert
a document into a collection on the client-side only, and then use upsert
later to add the document to servert-side collection?
有没有办法只在客户端将文档插入到集合中,然后使用upsert将文档添加到servert-side集合?
Here's what I tried:
这是我尝试过的:
I created a stub method that exists only on the client-side for inserting the document. The problem with this, is that when I click on the image, an empty field appears for a split-second, and then disappears again.
我创建了一个存在于客户端以便插入文档的存根方法。这个问题是,当我点击图像时,会出现一个空白字段,持续一秒钟,然后再次消失。
Here's the code:
这是代码:
image-tags.js
图像tags.js
if (Meteor.isClient) {
var isEditing;
Template.image.image_source = function () {
return "http://placekitten.com/g/800/600";
};
Template.tag.rendered = function(){
var tag = this.find('.tag');
if (isEditing && !tag.innerText) {
tag.focus();
}
}
Template.image.events({
'click img' : function (e) {
if (isEditing) {
isEditing = false;
} else {
isEditing = true;
var mouseX = e.offsetX;
var mouseY = e.offsetY;
// Tags.insert({x:mouseX, y:mouseY});
// Insert tag on the client-side only.
// Upsert later when the field is not empty.
Meteor.call('insertTag', {x:mouseX, y:mouseY});
}
},
'click .tag' : function (e) {
isEditing = true;
},
'blur .tag' : function (e) {
var currentTagId = this._id;
var text = e.target.innerText;
if(text) {
Tags.upsert(currentTagId, {$set: {name: text}});
} else {
Tags.remove(currentTagId);
}
}
});
Template.image.helpers({
tags: function() {
return Tags.find();
}
});
// Define methods for the collections
Meteor.methods({
insertTag: function(attr) {
Tags.insert({x:attr.x, y:attr.y});
}
});
}
// Collections
Tags = new Meteor.Collection('tags');
image-tags.html
图像tags.html
<head>
<title>Image Tagger</title>
</head>
<body>
{{> image}}
</body>
<template name="image">
<figure>
<img src="{{image_source}}" />
<figcaption class="tags">
{{#each tags}}
{{> tag}}
{{/each}}
</figcaption>
</figure>
</template>
<template name="tag">
<div class="tag" contenteditable style="left: {{x}}px; top: {{y}}px;">
{{name}}
</div>
</template>
2 个解决方案
#1
4
You should store the temporary tag (and probably your isEditing
var) in Session
:
您应该在Session中存储临时标记(可能还有您的isEditing var):
Session.set("isEditing", true);
Session.set("newTag", {x:mouseX, y:mouseY});
You can also create a local collection by passing null
instead of a collection name when initializing it. However, Session
should work for what you're doing. Check out the leaderboard for an example.
您还可以通过在初始化时传递null而不是集合名称来创建本地集合。但是,Session应该适用于您正在做的事情。查看排行榜以获取示例。
Edit:
编辑:
<figcaption class="tags">
{{#each tags}}
{{> tag}}
{{/each}}
{{#with newTag}}
{{> tag}}
{{/with}}
</figcaption>
Template.image.newTag = function() {
return Session.get("newTag");
}
#2
0
If you create the collection on client-side only you might have problem if you are disconnected : your new docs won't be stored on server.
如果仅在客户端创建集合,则在断开连接时可能会出现问题:新文档将不会存储在服务器上。
To my mind the best way is to set a property "published" or "editing" or "status" (with value published / eiditing / ...) in your document. Then your publish methods should return :
在我看来,最好的方法是在您的文档中设置属性“已发布”或“编辑”或“状态”(值已发布/ eiditing / ...)。然后你的发布方法应该返回:
- All the documents of the current user
- 当前用户的所有文档
- All the documents "published" or not in "editing" status
- 所有文件“已发布”或未处于“编辑”状态
When a user create a document it's stored on server but with the editing status. then when you save you can decide to publish it, and then all other user will receive the document in their subscription.
当用户创建文档时,它存储在服务器上但具有编辑状态。然后,当您保存时,您可以决定发布它,然后所有其他用户将在其订阅中收到该文档。
Hope that alternative solution will help you
希望替代解决方案能够帮助您
#1
4
You should store the temporary tag (and probably your isEditing
var) in Session
:
您应该在Session中存储临时标记(可能还有您的isEditing var):
Session.set("isEditing", true);
Session.set("newTag", {x:mouseX, y:mouseY});
You can also create a local collection by passing null
instead of a collection name when initializing it. However, Session
should work for what you're doing. Check out the leaderboard for an example.
您还可以通过在初始化时传递null而不是集合名称来创建本地集合。但是,Session应该适用于您正在做的事情。查看排行榜以获取示例。
Edit:
编辑:
<figcaption class="tags">
{{#each tags}}
{{> tag}}
{{/each}}
{{#with newTag}}
{{> tag}}
{{/with}}
</figcaption>
Template.image.newTag = function() {
return Session.get("newTag");
}
#2
0
If you create the collection on client-side only you might have problem if you are disconnected : your new docs won't be stored on server.
如果仅在客户端创建集合,则在断开连接时可能会出现问题:新文档将不会存储在服务器上。
To my mind the best way is to set a property "published" or "editing" or "status" (with value published / eiditing / ...) in your document. Then your publish methods should return :
在我看来,最好的方法是在您的文档中设置属性“已发布”或“编辑”或“状态”(值已发布/ eiditing / ...)。然后你的发布方法应该返回:
- All the documents of the current user
- 当前用户的所有文档
- All the documents "published" or not in "editing" status
- 所有文件“已发布”或未处于“编辑”状态
When a user create a document it's stored on server but with the editing status. then when you save you can decide to publish it, and then all other user will receive the document in their subscription.
当用户创建文档时,它存储在服务器上但具有编辑状态。然后,当您保存时,您可以决定发布它,然后所有其他用户将在其订阅中收到该文档。
Hope that alternative solution will help you
希望替代解决方案能够帮助您