1
\$\begingroup\$

I am working on a library which does DOM hide and show based on other DOM elements.

I have written a basic structure for the library.

The below is the code to handle DOM elements hiding when a checkbox is checked and unchecked.

My overall goal is to make this library extensible and maintainable.

Am I following SOLID principles? Is there any better way to do it? Are there any design patterns to follow?

// basic data structure of config object
var rules = [
  {
    sourceId: 'mainCheckbox',
    targetId: 'exampleDiv1',
    ruleType: 'onlyOnChecked',
    targetVisibilityOnChecked: 'hide', // show / hide
    targetVisibilityOnUnchecked: 'show',
    doNotReset: false
  }
]

var ruleToProcessorMap = {
  onlyOnChecked: OnlyOnCheckedRuleProcessor
}

var RuleEngine = {}

RuleEngine.run = function(rules) {
  var ruleIndex
  for (ruleIndex = 0; ruleIndex < rules.length; rules++) {
    this.processRule(rules[ruleIndex])
  }
}

RuleEngine.processRule = function(ruleObj) {
  var ruleProcessor = new ruleToProcessorMap[ruleObj.ruleType](ruleObj)
  ruleProcessor.process()
}

function OnlyOnCheckedRuleProcessor(options) {
  this.options = options || {}
}

OnlyOnCheckedRuleProcessor.prototype.process = function() {
  var $sourceId = $id(this.options.sourceId),
    ctx = this

  $sourceId.on('click', onSourceClick)

  function onSourceClick() {
    var elementVisibilityHandler = new ElementVisibilityHandler({
        elementId: ctx.options.targetId,
        doNotReset: ctx.options.doNotReset
      }),
      show = elementVisibilityHandler.show,
      hide = elementVisibilityHandler.hide

    var visibilityMap = {
      show: show,
      hide: hide
    }

    var onCheckedFunc = visibilityMap[ctx.options.targetVisibilityOnChecked]
    var onUncheckedFunc = visibilityMap[ctx.options.targetVisibilityOnUnchecked]

    if ($sourceId.is(':checked')) {
      onCheckedFunc.call(elementVisibilityHandler)
    } else {
      onUncheckedFunc.call(elementVisibilityHandler)
    }
  }
}

function ElementVisibilityHandler(options) {
  this.options = options || {}

  this.$element = $id(options.elementId)
}

ElementVisibilityHandler.prototype.show = function() {
  if (isContainerElement(this.$element)) {
    if (this.options.doNotReset) {
      simpleShow(this.$element)
    } else {
      showWithChildren(this.$element)
    }
  }
}

ElementVisibilityHandler.prototype.hide = function() {
  if (isContainerElement(this.$element)) {
    if (this.options.doNotReset) {
      simpleHide(this.$element)
    } else {
      hideAndResetChildren(this.$element)
    }
  }
}

function simpleHide($element) {
  return $element.hide()
}

function hideAndResetChildren($element) {
  var $children = simpleHide($element)
    .children()
    .hide()

  $children.find('input:checkbox').prop('checked', false)

  $children.find('textarea, input').val('')
}

function simpleShow($element) {
  return $element.show()
}

function showWithChildren($element) {
  simpleShow($element)
    .children()
    .show()
}

function $id(elementId) {
  return $('#' + elementId)
}

function isContainerElement($element) {
  if (typeof $element === 'string') {
    $element = $id($element)
  }

  return $element.prop('tagName').toLowerCase()
}

// execution starts here
RuleEngine.run(rules)

```
\$\endgroup\$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.