where should I put the jquery call to a plugin inside a Batman.js app?

68 Views Asked by At

I have a plugin called select2, I normally invoke the plugin inside my javascript file like this: $(document).ready(function() { $("#e1").select2(); });

but on my Batman app I'm not sure where should I put it. I could place it inside the libs folder (my_helper.js)but it doesn't work, is there another place where conventionally this jquery call should go?

Thanks.

1

There are 1 best solutions below

0
On

EDIT: This can get more complicated if you have a data-foreach to generate the options. I've added a more robust Select2View at the end of this answer!


I'm guessing document.ready is fired before Batman views actually render, so the DOM isn't populated yet. The jQuery call doesn't match any elements, since they aren't on the page yet.

Try defining a custom view, hooking into its lifecycle, then binding to that view in your HTML.

Custom view:

class MyApp.Select2View extends Batman.View
  viewDidAppear: -> 
    $("#e1").select2();

in your HTML:

<div data-view='Select2View'>
   <select id='e1' data-bind='item.value'>
     <!-- your options here! -->
   </select>
</div> 

More about view lifecycle callbacks here: http://batmanjs.org/docs/views.html#view-lifecycle


Other Select2View:

(Also on pastebin)

# Use select2 with a batman.js view binding
#
# Usage:
#   <select data-view='Select2View' data-view-bind='myRecord.myProperty'>
#     <option data-foreach-opt='myOptions' data-bind='opt.name' data-bind-value='opt.id'>
#   </select>
#
# Note that the property name is passed in as `data-view-bind`. This goes with `@option 'bind'` in the View definition.

class App.Select2View extends Batman.View
  @option 'bind', 'placeholder'
  constructor: ->
    super
    @on 'childBindingAdded', @childBindingAdded

  _addChildBinding: (binding) ->
    super
    @fire('childBindingAdded', binding)

  ready: ->
    unless @select2
      options = { minimumResultsForSearch: 12 }
      options.minimumResultsForSearch = -1 if $(@node).hasClass("select2--nosearch")
      if placeholder = @get('placeholder')
        options.placeholder = placeholder
      @select2 = $(@node).select2(options)
      @select2.on 'change', @select2Changed
    @dataChanged()

  select2Changed: =>
    value = @select2.select2("val")
    # coercion to integer borrowed from old Batman.js code https://github.com/batmanjs/batman/commit/b9c208a5f232fd505d58ac13dbdcb0ad00887457
    if (typeof value is "string") and value.match(/[^0-9]/) is null and "#{coercedValue = parseInt(value, 10)}" is value
      value = coercedValue
    @set 'bind', value

  childBindingAdded: (binding) =>
    if binding instanceof Batman.DOM.IteratorBinding
      binding.backingView.on 'itemsWereRendered', => @dataChanged()
    @dataChanged()

  dataChanged: ->
    if @select2 and (typeof @bind isnt 'undefined')
      @select2.select2("val", @bind)

  @accessor 'bind',
    get: ->
      @bind
    set: (name, value) ->
      @bind = value
      @dataChanged()