从插件外部访问jquery / coffeescript插件的方法

时间:2012-04-12 15:40:03

标签: jquery function plugins coffeescript public

我知道这个问题已被多次询问,但所有答案都让我感到困惑,因为我不确定如何将coffeescript代码编译成指定的jquery代码。

这是我到目前为止所做的:

pluginName = 'tagbox'

states = 
  none: 0
  typing: 1
  altering: 2        

defaults =
  editing: true
  tags: []

class Plugin
  constructor: (@element, options) ->
    @options = $.extend {}, defaults, options
    @_defaults = defaults
    @_states = states
    @state = states.none
    @_name = 'tagbox'
    @currentTag = $("<div class='ui-individualtag'></div>")

  # this is the public method I want
  setCurrentTag: (tagText) ->
    @currentTag.text(tagText)

$.fn[pluginName] = (options) ->
  @each ->
    if !$.data(this, "plugin_#{pluginName}")
      $.data(@, "plugin_#{pluginName}", new Plugin(@, options))
)(jQuery, window, document)

然后在另一个脚本中,我希望能够像这样访问setCurrentTag方法:

tagbox = $('#tagbox').tagbox()
tagbox.setCurrentTag("hello world")

让我知道它是否有助于显示在jquery中编译的内容。

1 个答案:

答案 0 :(得分:2)

您的问题是tagbox

tagbox = $('#tagbox').tagbox()

将是一个jQuery对象,并且不会有setCurrentTag方法。您不希望尝试更改此操作,因为这会破坏通常的jQuery链接行为。解决此问题的一种方法是为tagbox插件提供足够的智能来解析其参数,以便您可以在以下位置传递方法名称:

$('#tagbox').tagbox('setCurrentTag', 'hello world')

这是jQuery-UI所采用的方法,因此很多jQuery人都应该熟悉它。

您需要做的就是修改$.fn.tagbox看起来更像这样:

$.fn[pluginName] = (options = {}) ->
  if $.isPlainObject options
    @each ->
      if !$.data(@, "plugin_#{pluginName}")
        $.data(@, "plugin_#{pluginName}", new Plugin(@, options))
  else
    args = Array.prototype.slice.call(arguments);
    @each ->
      p = $.data(@, "plugin_#{pluginName}")
      p[args[0]](args[1])

演示:http://jsfiddle.net/ambiguous/q2U7d/

有些注意事项:

  1. 我添加了默认设置((options = {}) ->),以便options始终在那里。
  2. 我们可以使用$.isPlainObject检查我们是否有选项对象,如果没有选项,那么我们可以假设我们正在进行方法调用。这就是为什么我们想要 1 中的默认值。
  3. 我们使用Array.prototype.slice.call作为黑客将类似数组的arguments转换为真实数组,以便更轻松地使用它。我们不必这样做,但如果我们想要使用数组方法(例如pop)并且我们需要引用arguments中的外部@each,它可以节省一些混淆。无论如何回调:arguments是上下文敏感的,就像{Coffee(Java)Script中的this一样。