fatfreecrm/fat_free_crm

View on GitHub
app/assets/javascripts/crm_classes.js.coffee

Summary

Maintainability
Test Coverage
# Copyright (c) 2008-2013 Michael Dvorkin and contributors.
#
# Fat Free CRM is freely distributable under the terms of MIT license.
# See MIT-LICENSE file or http://www.opensource.org/licenses/mit-license.php
#------------------------------------------------------------------------------
(($) ->

  window.crm ||= {}

  class crm.Popup

    #----------------------------------------------------------------------------
    constructor: (options = {}) ->
      @options = $.extend(
        trigger: "#trigger" # #id of the element that triggers on_mouseover popup.
        target: "#popup" # #id of the popup div that is shown or hidden.
        appear: 0 # duration of EffectAppear or 0 for show().
        fade: 0 # duration of EffectFade or 0 for hide().
        under: false # true to show popup right under the trigger div.
        zindex: 100 # zIndex value for the popup.
        before_show: $.noop # before show callback.
        before_hide: $.noop # before hide callback.
        after_show: $.noop # after show callback.
        after_hide: $.noop # after hide callback.
      , options)
      @popup = $(@options.target) # actual popup div.
      @setup_toggle_observer()
      @setup_hide_observer()


    #----------------------------------------------------------------------------
    setup_toggle_observer: ->
      $(@options.trigger).on "click", (e) =>
        @toggle_popup e


    #----------------------------------------------------------------------------
    setup_hide_observer: ->
      $(document).on "click", (e) =>
        if @popup and @popup.css('display') isnt 'none'
          clicked_on = $(e.target).closest("div")
          @hide_popup e  if clicked_on.length is 0 or ('#' + clicked_on.attr('id')) isnt @options.target


    #----------------------------------------------------------------------------
    show_popup: (e) ->
      e.preventDefault()
      e.stopPropagation()
      @popup.css zIndex: @options.zindex
      
      # Add custom "trigger" attribute to the popup div so we could check who has triggered it.
      @popup.attr trigger: @options.trigger
      @options.before_show e
      unless @options.appear
        @popup.show()
        @set_position e
        @options.after_show e
      else
        @set_position e
        @popup.fadeIn(
          @options.appear
          @options.after_show
        )


    #----------------------------------------------------------------------------
    toggle_popup: (e) ->
      if @popup.filter(':visible').length
        unless @options.trigger is @popup.attr("trigger")
          
          # Currently shown popup was opened by some other trigger: hide it immediately
          # without any fancy callbacks, then show this popup.
          @popup.hide()
          @show_popup e
        else
          @hide_popup e
      else
        @show_popup e


    #----------------------------------------------------------------------------
    hide_popup: (e) ->
      e.preventDefault()  if e
      @options.before_hide e
      unless @options.fade
        @popup.hide()
        @options.after_hide e
      else
        @popup.fadeOut(
          @options.fade
          @options.after_hide
        )

    set_position: (e) ->
      if @options.under
        under = $(@options.under)
        popup = $(@popup)
        offset = under.offset()
        x = (offset.left + under.width() - popup.width()) + "px"
        y = (offset.top + under.height()) + "px"
        @popup.css
          left: x
          top: y



  class crm.Menu

    #----------------------------------------------------------------------------
    constructor: (options = {}) ->
      @options = $.extend(
        trigger: "#menu" # #id of the element clicking on which triggers dropdown menu.
        align: "left" # align the menu left or right
        appear: 0 # duration of EffectAppear or 0 for show().
        fade: 0 # duration of EffectFade or 0 for hide().
        width: 0 # explicit menu width if set to non-zero
        zindex: 100 # zIndex value for the popup.
        before_show: $.noop # before show callback.
        before_hide: $.noop # before hide callback.
        after_show: $.noop # after show callback.
        after_hide: $.noop # after hide callback.
      , options)
      @build_menu()
      @setup_show_observer()
      @setup_hide_observer()


    #----------------------------------------------------------------------------
    build_menu: ->
      @menu = $("<div>",
        class: "menu"
        style: "display:none;";
        on:
          click: (e) ->
            e.preventDefault()
      )
      @menu.css width: @options.width + "px"  if @options.width
      @menu.appendTo(document.body)

      ul = $("<ul>")
      ul.appendTo(@menu)

      for item in @options.menu_items
        li = $("<li>")
        li.appendTo(ul)
        a = $("<a>",
          href: "#"
          title: item.name
          on:
            click: @select_menu.bind(this)
        ).html(item.name)
        a.data(on_select: item.on_select)  if item.on_select
        a.appendTo(li)


    #----------------------------------------------------------------------------
    setup_hide_observer: ->
      $(document).on "click", (e) =>
        @hide_menu(e)  if @menu and @menu.css('display') isnt 'none'


    #----------------------------------------------------------------------------
    setup_show_observer: ->
      $(@options.trigger).on "click", (e) =>
        @show_menu(e)  if @menu and @menu.css('display') is 'none'


    #----------------------------------------------------------------------------
    hide_menu: (e) ->
      @options.before_hide e
      unless @options.fade
        @menu.hide()
        @options.after_hide e
      else
        @menu.fadeOut(
          @options.fade
          @options.after_hide
        )


    #----------------------------------------------------------------------------
    show_menu: (e) ->
      e.preventDefault()
      e.stopPropagation()
      $el = $(e.target)
      offset = $el.offset()
      x = offset.left + "px"
      y = offset.top + $el.height() + "px"
      x = (offset.left - (@options.width - $el.width() + 1)) + "px"  if @options.align is "right"
      @menu.css
        left: x
        top: y
        zIndex: @options.zindex
      @options.before_show e
      unless @options.appear
        @menu.show()
        @options.after_show e
      else
        @menu.fadeIn(
          @options.appear
          @options.after_show
        )

      @event = e


    #----------------------------------------------------------------------------
    select_menu: (e) ->
      e.preventDefault()
      $el = $(e.target)
      if on_select = $el.data('on_select')
        @hide_menu()
        on_select @event

) jQuery