 # but in theory could be used to call any `window.jQuery.fn` function
 Aui.modules = (jQuery?.site?.settings?.modules or []).slice()
 
-## internal cache of options passed to modules.
-moduleCache = {}
+## internal global cache of options passed to module functions.
+cache = {}
+
 ## internal class <Aui.Module/>
 # This class provides support for `Aui.modules` and handles calling jQuery.fn[module] calls
 Aui.Module = React.createClass
   render: -> React.Children.only @props.children
-  componentDidMount: -> @callModules @props.children.props
-  componentWillReceiveProps: (props) -> @callModules props.children.props
+  preventDefault: (event) ->
+    event?.preventDefault?()
+  componentDidMount: ->
+    if @props.options.preventDefaultSubmit and 'form' of @props.modules
+      jQuery(React.findDOMNode @).on 'submit', @preventDefault
+    @callModules @props.children.props
+  componentWillReceiveProps: (props) ->
+    @callModules props.children.props
   callModules: (props) ->
     $element = jQuery React.findDOMNode @
-    moduleId = $element.attr 'data-reactid'
-    if moduleId isnt @moduleId
-      console.log 'moduleId isnt @moduleId', moduleId, @moduleId
-      delete moduleCache[@moduleId]
-    @moduleId = moduleId
-    moduleCache[@moduleId] or= {}
-    for module, options in @props.modules
-      cacheOptions = JSON.stringify options
-      if moduleCache[@moduleId][module] isnt cacheOptions
-        moduleCache[@moduleId][module] = cacheOptions
-        ($element)[module] @props.children.props[module]...
+    @id = $element.attr 'data-reactid'
+    cache[@id] or= {}
+    for own module, options of @props.modules
+      stringifiedOptions = JSON.stringify options
+      if cache[@id][module] isnt stringifiedOptions
+        cache[@id][module] = stringifiedOptions
+        console.log module, stringifiedOptions, React.findDOMNode @
+        $element[module]? @props.children.props[module]...
     return
   componentWillUnmount: ->
-    delete moduleCache[@moduleId]
+    $element = jQuery React.findDOMNode @
+    if 'form' of @props.modules
+      $element.off 'submit', @preventDefault
+    unless @props.options.disableSemantic
+      for module in @props.modules
+        $element[module]? 'destroy'
+    delete cache[@id]
+    console.log 'componentWillUnmount', React.findDOMNode @
+    #throw new Error 'STOP drop and roll...'
 window?.Aui = Aui
 module?.exports = Aui

  disableSemantic: not jQuery?.site?.settings?.modules?
  # do not recursively Aui.classify children by default.
  ignoreChildren: no

## internal class `AuiOptions({options})`
# defaults all Aui options

    for own key, value of element.props
      classNames[key] = yes if value is yes
      if (not options.disableModules) and (Array.isArray value) and (key in Aui.modules)
        classNames[key] = yes
        modules or= {}
        modules[key] = value
      props[key] = value
    props.className = Object.keys(classNames).join ' '
    unless props.className.length
      delete props.className
    #console.log modules, (if typeof element.type is 'string' then element.type else 'Component'), props.className or ''
    element = React.cloneElement element, props, if options.ignoreChildren then element.props.children else React.Children.map element.props.children, classify
    if modules
      React.createElement Aui.Module, { modules, options }, element
    else element
  classify element

