如何验证Firefox扩展程序的首选项?

时间:2012-10-09 14:40:52

标签: firefox firefox-addon xul

在Firefox扩展中验证偏好值的普遍接受的方法是什么,特别是在XUL中使用prefwindow机制时?

我在我的一个扩展中引入了一些新的首选项,我希望在首选项窗口关闭之前进行验证。如果出现错误,应允许用户更正问题,然后继续。我看到prefwindow元素在这方面有两个可能有用的功能:

前者似乎有一个相关的错误(Bug 474527),阻止prefwindow在从该函数返回false时保持打开状态。这很糟糕,因为它不会让用户立即纠正错误。

后者似乎存在以下问题:首选项在退出之前被保存,这使得首选项在内部处于错误状态。

此外,prefwindow机制支持browser.preferences.instantApply选项,其中在更新关联控件时立即写入首选项值。这使得验证更加棘手。有没有一种干净的方法来验证Firefox扩展中的自定义首选项,允许用户纠正任何潜在的错误?

2 个答案:

答案 0 :(得分:2)

通常,您希望在更改时验证首选项。 onchange attribute(以及相应的change事件)适用于:

<preference name="preference.name" onchange="validate(this);"/>

在首选项值更改后触发事件。有两个缺点:

  • 如果instantApply新优惠价值已经保存,则验证和拒绝为时已晚。
  • 对于文本字段,每次键入新字符时都会保存首选项。如果您在用户仍在键入时报告验证失败,则会变得很难看。

您可以通过拦截实际输入字段的更改事件来解决第一个问题。例如,对于文本字段,您可以执行以下操作:

<input preference="preference.name"
    oninput="if (!validate(this)) event.stopPropagation();"
    onchange="if (!validate(this)) { event.stopPropagation(); this.focus(); }"/>

因此,未正确验证的更改不会冒泡到<prefpane>元素,也不会保存。要收听的事件包括:inputchange用于文本字段,command用于按钮和复选框,select用于<colorpicker>元素。

第二个问题很棘手。您仍然希望在输入发生时验证输入,然后立即显示消息将是错误的UI。我认为最好的解决方案是首先假设每个输入字段仍处于“进行中”状态。当您第一次在该字段上看到blur事件时,您只需设置一个标记,表示该值已完成。那时您可以在必要时显示验证消息(理想情况下红色文本显示在您的首选项页面中,而不是模态提示)。

所以说明最终解决方案可能是什么样的(未经测试的代码,但过去我使用过类似的代码):

<description id="error" hidden="true">Invalid preference value</description>

<input preference="preference.name"
    _errorText="error"
    onblur="validate(event);"
    oninput="validate(event);"
    onchange="validate(event);/>

<script>
  function validate(event)
  {
    // Perform actual validation
    var field = event.target;
    var valid = isValid(field);

    // If this is the blur event then the element is no longer "in progress"
    if (event.type == "blur")
    {
      field._inputDone = true;
      if (!valid)
        field.focus();
    }

    // Prevent preferences changing to invalid value
    if (!valid)
      event.stopPropagation();

    // Show or hide error text
    var errorText = document.getElementById(field.getAttribute("_errorText"));
    errorText.hidden = valid || !field._inputDone;
  }
</script>

答案 1 :(得分:1)

如果您希望在字段更改后立即验证值,以便处理instantApply案例,则可以挂钩各个字段的更改事件(例如oninput表示{{{3}} 1}})。如果值无效,则显示错误消息并强制将焦点返回到字段。您可以自动将其设置回有效值,也可以阻止用户关闭对话框,直到修复为止。