4

我是 Parse 的新手,我正在尝试做一个登录页面。我拥有的是用户名(不是电子邮件)和密码,这是可行的。我还为注册有一个用户名、密码和电子邮件字段。这也有效。我想要做的是添加一种方式,当用户输入他们的电子邮件地址时,解析将向他们发送电子邮件。我正在使用 JavaScript SDK。

<!DOCTYPE html>
<html>   
<meta charset="utf-8">
<title>Parse JavaScript Todo App</title>
<link href="css/todos.css" media="all" rel="stylesheet" type="text/css"/>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="js/underscore-1.1.6.js"></script>
<script src="//www.parsecdn.com/js/parse-1.1.15.min.js"></script>
<script src="js/todos.js"></script>
<body>

<!-- Todo App Interface -->

<div id="todoapp">
  <div class="title">
    <h1>Parse Todos</h1>
  </div>

  <div class="content">
  </div>
</div>

<div id="credits">
  Powered by <a href="https://www.parse.com">Parse</a> using the <a href="https://www.parse.com/docs/js_guide">JavaScript SDK</a>
</div>

<!-- Templates -->

<script type="text/template" id="login-template">
  <header id="header"></header>
  <div class="login">
    <form class="login-form">
      <h2>Log In</h2>
      <div class="error" style="display:none"></div>
      <input type="text" id="login-username" placeholder="Username" />
      <input type="password" id="login-password" placeholder="Password" />
      <button>Log In</button>
    </form>

    <form class="signup-form">
      <h2>Sign Up</h2>
      <div class="error" style="display:none"></div>
      <input type="text" id="signup-username" placeholder="Username" />
      <input type="password" id="signup-password" placeholder="Create a Password" />
      <input type="email" id="signup-email" placeholder="Enter your Email" />
      <button>Sign Up</button>
      <a href="passReset.htm">Forgot Password?</a>
  </div>
</script>

<script type="text/template" id="manage-todos-template">
  <div id="user-info">
    Signed in as <%= Parse.User.current().get("username") %> (<a href="#" class="log-out">Log out</a>)
  </div>

  <div class="section">

    <header id="header">
      <input id="new-todo" placeholder="What needs to be done?" type="text" />
    </header>

    <div id="main">
      <input id="toggle-all" type="checkbox">
      <label for="toggle-all">Mark all as complete</label>

      <ul id="todo-list">
        <img src='images/spinner.gif' class='spinner' />
      </ul>
    </div>

    <div id="todo-stats"></div>
  </div>
</script>

<script type="text/template" id="item-template">
  <li class="<%= done ? 'completed' : '' %>">
<div class="view">
  <input class="toggle" type="checkbox" <%= done ? 'checked="checked"' : '' %>>
  <label class="todo-content"><%= content %></label>
  <button class="todo-destroy"></button>
</div>
<input class="edit" value="<%= content %>">
  </li>
</script>

<script type="text/template" id="stats-template">
  <footer id="footer">
<span id="todo-count"><strong><%= remaining %></strong> <%= remaining == 1 ? 'item' : 'items' %> left</span>
<ul id="filters">
  <li>
    <a href="javascript:void(0)" id="all" class="selected">All</a>
  </li>
  <li>
    <a href="javascript:void(0)" id="active">Active</a>
  </li>
  <li>
    <a href="javascript:void(0)" id="completed">Completed</a>
  </li>
</ul>
<button id="clear-completed">Clear completed (<%= done %>)</button>
  </footer>
</script>

接下来是实现上述工作的 JavaScript。

$(function() {

Parse.$ = jQuery;

// Initialize Parse with your Parse application javascript keys
Parse.initialize("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
               "XXXXXXXXXXXXXXXXXXXXXXX");

// Todo Model
// ----------

// Our basic Todo model has `content`, `order`, and `done` attributes.
 var Todo = Parse.Object.extend("Todo", {
// Default attributes for the todo.
defaults: {
  content: "empty todo...",
  done: false
},

// Ensure that each todo created has `content`.
initialize: function() {
  if (!this.get("content")) {
    this.set({"content": this.defaults.content});
  }
},

// Toggle the `done` state of this todo item.
toggle: function() {
  this.save({done: !this.get("done")});
}
});

// This is the transient application state, not persisted on Parse
var AppState = Parse.Object.extend("AppState", {
defaults: {
  filter: "all"
}
});

// Todo Collection
// ---------------

var TodoList = Parse.Collection.extend({

// Reference to this collection's model.
model: Todo,

// Filter down the list of all todo items that are finished.
done: function() {
  return this.filter(function(todo){ return todo.get('done'); });
},

// Filter down the list to only todo items that are still not finished.
remaining: function() {
  return this.without.apply(this, this.done());
},

// We keep the Todos in sequential order, despite being saved by unordered
// GUID in the database. This generates the next order number for new items.
nextOrder: function() {
  if (!this.length) return 1;
  return this.last().get('order') + 1;
},

// Todos are sorted by their original insertion order.
comparator: function(todo) {
  return todo.get('order');
}

});

// Todo Item View
// --------------

// The DOM element for a todo item...
var TodoView = Parse.View.extend({

//... is a list tag.
tagName:  "li",

// Cache the template function for a single item.
template: _.template($('#item-template').html()),

// The DOM events specific to an item.
events: {
  "click .toggle"              : "toggleDone",
  "dblclick label.todo-content" : "edit",
  "click .todo-destroy"   : "clear",
  "keypress .edit"      : "updateOnEnter",
  "blur .edit"          : "close"
},

// The TodoView listens for changes to its model, re-rendering. Since there's
// a one-to-one correspondence between a Todo and a TodoView in this
// app, we set a direct reference on the model for convenience.
initialize: function() {
  _.bindAll(this, 'render', 'close', 'remove');
  this.model.bind('change', this.render);
  this.model.bind('destroy', this.remove);
},

// Re-render the contents of the todo item.
render: function() {
  $(this.el).html(this.template(this.model.toJSON()));
  this.input = this.$('.edit');
  return this;
},

// Toggle the `"done"` state of the model.
toggleDone: function() {
  this.model.toggle();
},

// Switch this view into `"editing"` mode, displaying the input field.
edit: function() {
  $(this.el).addClass("editing");
  this.input.focus();
},

// Close the `"editing"` mode, saving changes to the todo.
close: function() {
  this.model.save({content: this.input.val()});
  $(this.el).removeClass("editing");
},

// If you hit `enter`, we're through editing the item.
updateOnEnter: function(e) {
  if (e.keyCode == 13) this.close();
},

// Remove the item, destroy the model.
clear: function() {
  this.model.destroy();
}

});

// The Application
// ---------------

// The main view that lets a user manage their todo items
var ManageTodosView = Parse.View.extend({

// Our template for the line of statistics at the bottom of the app.
statsTemplate: _.template($('#stats-template').html()),

// Delegated events for creating new items, and clearing completed ones.
events: {
  "keypress #new-todo":  "createOnEnter",
  "click #clear-completed": "clearCompleted",
  "click #toggle-all": "toggleAllComplete",
  "click .log-out": "logOut",
  "click ul#filters a": "selectFilter"
},

el: ".content",

// At initialization we bind to the relevant events on the `Todos`
// collection, when items are added or changed. Kick things off by
// loading any preexisting todos that might be saved to Parse.
initialize: function() {
  var self = this;

  _.bindAll(this, 'addOne', 'addAll', 'addSome', 'render', 'toggleAllComplete',    'logOut', 'createOnEnter');

  // Main todo management template
  this.$el.html(_.template($("#manage-todos-template").html()));

  this.input = this.$("#new-todo");
  this.allCheckbox = this.$("#toggle-all")[0];

  // Create our collection of Todos
  this.todos = new TodoList;

  // Setup the query for the collection to look for todos from the current user
  this.todos.query = new Parse.Query(Todo);
  this.todos.query.equalTo("user", Parse.User.current());

  this.todos.bind('add',     this.addOne);
  this.todos.bind('reset',   this.addAll);
  this.todos.bind('all',     this.render);

  // Fetch all the todo items for this user
  this.todos.fetch();

  state.on("change", this.filter, this);
},

// Logs out the user and shows the login view
logOut: function(e) {
  Parse.User.logOut();
  new LogInView();
  this.undelegateEvents();
  delete this;
},

// Re-rendering the App just means refreshing the statistics -- the rest
// of the app doesn't change.
render: function() {
  var done = this.todos.done().length;
  var remaining = this.todos.remaining().length;

  this.$('#todo-stats').html(this.statsTemplate({
    total:      this.todos.length,
    done:       done,
    remaining:  remaining
  }));

  this.delegateEvents();

  this.allCheckbox.checked = !remaining;
},

// Filters the list based on which type of filter is selected
selectFilter: function(e) {
  var el = $(e.target);
  var filterValue = el.attr("id");
  state.set({filter: filterValue});
  Parse.history.navigate(filterValue);
},

filter: function() {
  var filterValue = state.get("filter");
  this.$("ul#filters a").removeClass("selected");
  this.$("ul#filters a#" + filterValue).addClass("selected");
  if (filterValue === "all") {
    this.addAll();
  } else if (filterValue === "completed") {
    this.addSome(function(item) { return item.get('done') });
  } else {
    this.addSome(function(item) { return !item.get('done') });
  }
},

// Resets the filters to display all todos
resetFilters: function() {
  this.$("ul#filters a").removeClass("selected");
  this.$("ul#filters a#all").addClass("selected");
  this.addAll();
},

// Add a single todo item to the list by creating a view for it, and
// appending its element to the `<ul>`.
addOne: function(todo) {
  var view = new TodoView({model: todo});
  this.$("#todo-list").append(view.render().el);
},

// Add all items in the Todos collection at once.
addAll: function(collection, filter) {
  this.$("#todo-list").html("");
  this.todos.each(this.addOne);
},

// Only adds some todos, based on a filtering function that is passed in
addSome: function(filter) {
  var self = this;
  this.$("#todo-list").html("");
  this.todos.chain().filter(filter).each(function(item) { self.addOne(item) });
},

// If you hit return in the main input field, create new Todo model
createOnEnter: function(e) {
  var self = this;
  if (e.keyCode != 13) return;

  this.todos.create({
    content: this.input.val(),
    order:   this.todos.nextOrder(),
    done:    false,
    user:    Parse.User.current(),
    ACL:     new Parse.ACL(Parse.User.current())
  });

  this.input.val('');
  this.resetFilters();
},

// Clear all done todo items, destroying their models.
clearCompleted: function() {
  _.each(this.todos.done(), function(todo){ todo.destroy(); });
  return false;
},

toggleAllComplete: function () {
  var done = this.allCheckbox.checked;
  this.todos.each(function (todo) { todo.save({'done': done}); });
}
});

var LogInView = Parse.View.extend({
events: {
  "submit form.login-form": "logIn",
  "submit form.signup-form": "signUp",
  "submit form.reset-form": "reset"
},

el: ".content",

initialize: function() {
  _.bindAll(this, "logIn", "signUp","reset");
  this.render();
},

logIn: function(e) {
  var self = this;
  var username = this.$("#login-username").val();
  var password = this.$("#login-password").val();

  Parse.User.logIn(username, password, {
    success: function(user) {
      new ManageTodosView();
      self.undelegateEvents();
      delete self;
    },

    error: function(user, error) {
      self.$(".login-form .error").html("Invalid username or password. Please try again.").show();
      this.$(".login-form button").removeAttr("disabled");
    }
  });

  this.$(".login-form button").attr("disabled", "disabled");

  return false;
},

signUp: function(e) {
  var self = this;
  var username = this.$("#signup-username").val();
  var password = this.$("#signup-password").val();
  var email = this.$("#signup-email").val();

  Parse.User.signUp(username, password,{email:email, ACL: new Parse.ACL() }, {
    success: function(user) {
      new ManageTodosView();
      self.undelegateEvents();
      delete self;
    },

    error: function(user, error) {
      self.$(".signup-form .error").html(error.message).show();
      this.$(".signup-form button").removeAttr("disabled");
    }
  });

  this.$(".signup-form button").attr("disabled", "disabled");

  return false;
},

render: function() {
  this.$el.html(_.template($("#login-template").html()));
  this.delegateEvents();
}
});

// The main view for the app
var AppView = Parse.View.extend({
// Instead of generating a new element, bind to the existing skeleton of
// the App already present in the HTML.
el: $("#todoapp"),

initialize: function() {
  this.render();
},

render: function() {
  if (Parse.User.current()) {
    new ManageTodosView();
  } else {
    new LogInView();
  }
}
});

var AppRouter = Parse.Router.extend({
routes: {
  "all": "all",
  "active": "active",
  "completed": "completed"
},

initialize: function(options) {
},

all: function() {
  state.set({ filter: "all" });
},

active: function() {
  state.set({ filter: "active" });
},

completed: function() {
  state.set({ filter: "completed" });
}
});

var state = new AppState;

new AppRouter;
new AppView;
Parse.history.start();
});

我知道

Parse.User.requestPasswordReset("email@example.com", {
success: function() {
// Password reset request was sent successfully
},
error: function(error) {
// Show the error message somewhere
alert("Error: " + error.code + " " + error.message);
}
});

但无法弄清楚如何让它工作。

提前致谢。

托马斯。

编辑:基本上我要问的是如何在 Parse 中设置重置/忘记密码链接/按钮。

我现在拥有的是一个电子邮件地址和一个按钮的输入。单击按钮时,我希望 Parse 向用户发送一封电子邮件,允许用户更改其密码。

我已经更改了上面的代码,并且有了更多的知识,我将问题缩小到我认为以下

reset: function (e) {
        var self = this;
        var email = this.$("reset-email").val();

        Parse.User.requestPasswordReset({email:email}, {
            success: function () {
                new LogInView();
                self.undelegateEvents();
                delete self;
            },
            error: function(error) {
                // Show the error message somewhere
                self.$(".reset-form .error").html(error.message).show();
                this.$(".reset-form button").removeAttr("disabled");
            }

        });

        this.$(".reset-form button").attr("disabled", "disabled");

        return false;
    },

我得到的错误是:无效的电子邮件{}

对不起,这么草率的帖子我完全迷路了。

最终编辑:

我得到了上述工作问题在 Parse 论坛上得到了回答 https://www.parse.com/questions/parseuserrequestpasswordreset

4

1 回答 1

1

首先,您可以使用帮助程序 java 脚本函数检查给定的电子邮件是否有效,然后使用 Parse.User.requestPasswordReset 发出请求

function checkEmail(email)
{
    var atpos = email.indexOf("@");
    var dotpos = email.lastIndexOf(".");

    if (atpos<1 || dotpos<atpos+2 || dotpos+2>=email.length) 
    {
        return false;
    }
    return true;
}

function resetPassword()
{           
    var email = document.forms["resetpassword"]["email"].value;
    var emailIsValid = checkEmail(email);

    if (!emailIsValid)
    {
        window.alert("Not a valid e-mail address");
        return false;
    }

    Parse.User.requestPasswordReset(email, {
                success:function() {
                    window.alert("Password reset link has been sent to "+ email);
                    return true;
                },
                error:function(error) {
                    window.alert(error.message);
                    return false;
                }
            });
}
于 2015-06-08T22:54:12.487 回答