# ============================================================
# TBG switch v0.0.1
# ============================================================
# Copyright 2012 The Beans Group
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
plugin = ($)->
"use strict"
# SWITCH CLASS DEFINITION
#
# @example How to ensure plugin self initialises on element
#
...
#
# @example How to group switches and allow them to change state of other switches in that group
# ...
#
# @example How to toggle switch state
# ...
#
class Switch
# Construct a new Switch instance
#
# Set this.parent, this.target, this.group and this.container elements for this.el; set this.toggle if attribute present
#
# @param [Object] el HTMLElement, this.el, that acts as the switch
#
constructor: ( @el ) ->
@parent = if (parent = @el.parent('li')).length then parent else @el.parent()
@content = @_getContent @el
@toggle = @el.attr('data-switch-toggle')?
@group = if ( groupName = @el.attr('data-switch-group') ) then $("[data-switch-group='#{groupName}']")
@container = @el.closest 'ul'
activeClass: "is-active"
_constructor: Switch
# Click handler - If this.parent isn't active, close group if this.group defined and change state to true;
# if this.parent is active and this.toggle set then change state to false otherwise return undefined
#
click: ->
if @parent.hasClass(@activeClass)
if @toggle then return @changeStateTo false else return
@_closeGroup() if @group
@changeStateTo true
# Change active state of target content - add or remove activeClass from content and parent elements
#
# @param [Boolean] action true to addClass to elements, false to removeClass from elements
# @param [Array] elements array of jQuery wrapped HTMLElements - target content element and parent element
#
changeStateTo: (action, elements = [@content, @parent]) ->
el["#{if action then "add" else "remove"}Class"] @activeClass for el in elements
# Close group - if any content is active, get the target for that element's descendant link element and pass false and
# elements array [activeContent, activeEl] to switch group
#
# @private
#
_closeGroup: ->
if (activeEl = @container.find("li.#{@activeClass}")).length
activeContent = @_getContent activeEl.children('a')
@changeStateTo false, [activeContent, activeEl]
# Get target element to do switch on
#
# @private
# @param [Object] el jQuery wrapped HTMLElement to get target element from
# @return [Object] jQuery wrapped HTMLElement for el's target element
#
_getContent: ( el ) ->
$(el.attr 'href')
# SWITCH PLUGIN DEFINITION
# ==========================
$.fn.switch = ( option ) ->
this.each ->
$this = $(@)
data = $this.data 'switchPlugin'
if !data then $this.data 'switchPlugin', (data = new Switch $this)
if typeof option is 'string' then data[option]()
$.fn.switch.Constructor = Switch
# DATA API
# ===================================
$ ->
$('body').on 'click.switch.data-api', '[data-switch]', ( e ) ->
$el = if (el = $(e.target)).is('a') then el else el.closest('a')
$el.switch('click')
e.preventDefault()
do ( plugin ) ->
if typeof define is 'function' and define.amd
# AMD. Register as an anonymous module.
define(['jquery'], plugin);
else
# Browser globals
plugin(jQuery)