vodkabears / Remodal

No longer actively maintained.
http://vodkabears.github.io/remodal/
MIT License
2.76k stars 774 forks source link

Using this with pjax, im getting an error "TypeError: Cannot read property 'open' of undefined" #257

Open schester44 opened 7 years ago

schester44 commented 7 years ago

TypeError: Cannot read property 'open' of undefined - line 756.

the modal works great if the element that contains data-remodal-target="modal" is on the initial page that is loaded, however if I load the site on a different page then click through to the page that contains the data-remodal-target="modal", I get the above error when I click the element. I'm using pJax.. My guess is that the Remodal script is not recognizing the element after page load. Is there anything I can modify?

oBWolfstar commented 7 years ago

I'm also having this issue when reloading a list from Ajax (which uses remodals), after a little investigation I've found this occurs as the remodals are only initialised on page load (the document.ready function) on lines 737 to 735:

$(document).ready(function() {

    // data-remodal-target opens a modal window with the special Id
    $(document).on('click', '[data-' + PLUGIN_NAME + '-target]', function(e) {
      e.preventDefault();

      var elem = e.currentTarget;
      var id = elem.getAttribute('data-' + PLUGIN_NAME + '-target');
      var $target = $('[data-' + PLUGIN_NAME + '-id="' + id + '"]');

      $[PLUGIN_NAME].lookup[$target.data(PLUGIN_NAME)].open();
    });

    // Auto initialization of modal windows
    // They should have the 'remodal' class attribute
    // Also you can write the `data-remodal-options` attribute to pass params into the modal
    $(document).find('.' + NAMESPACE).each(function(i, container) {
      var $container = $(container);
      var options = $container.data(PLUGIN_NAME + '-options');

      if (!options) {
        options = {};
      } else if (typeof options === 'string' || options instanceof String) {
        options = parseOptions(options);
      }

      $container[PLUGIN_NAME](options);
    });

    // Handles the keydown event
    $(document).on('keydown.' + NAMESPACE, function(e) {
      if (current && current.settings.closeOnEscape && current.state === STATES.OPENED && e.keyCode === 27) {
        current.close();
      }
    });

    // Handles the hashchange event
    $(window).on('hashchange.' + NAMESPACE, handleHashChangeEvent);
  });

I believe that creating a manual version, which can be called on Ajax reload, would fix this as the page content needs to be fluid. Example:

function reloadModal() {

    // data-remodal-target opens a modal window with the special Id
    $(document).on('click', '[data-' + PLUGIN_NAME + '-target]', function(e) {
      e.preventDefault();

      var elem = e.currentTarget;
      var id = elem.getAttribute('data-' + PLUGIN_NAME + '-target');
      var $target = $('[data-' + PLUGIN_NAME + '-id="' + id + '"]');

      $[PLUGIN_NAME].lookup[$target.data(PLUGIN_NAME)].open();
    });

    // Auto initialization of modal windows
    // They should have the 'remodal' class attribute
    // Also you can write the `data-remodal-options` attribute to pass params into the modal
    $(document).find('.' + NAMESPACE).each(function(i, container) {
      var $container = $(container);
      var options = $container.data(PLUGIN_NAME + '-options');

      if (!options) {
        options = {};
      } else if (typeof options === 'string' || options instanceof String) {
        options = parseOptions(options);
      }

      $container[PLUGIN_NAME](options);
    });

    // Handles the keydown event
    $(document).on('keydown.' + NAMESPACE, function(e) {
      if (current && current.settings.closeOnEscape && current.state === STATES.OPENED && e.keyCode === 27) {
        current.close();
      }
    });

    // Handles the hashchange event
    $(window).on('hashchange.' + NAMESPACE, handleHashChangeEvent);
  };

That's all I could find, hopefully somebody reply soon as I'm trying to work around it but it's a pain, I tried creating my own manual version but the function was not picked up across my pages.

EDIT: Also the error does not trigger when using a href rather than the data-remodal-target however the remodal still fails to trigger!.

Hope it helps!

oBWolfstar commented 7 years ago

Please NOTE: This is not an official fix, I'm merely a user whom has found a work around

Found a small work around which suits me fine, when a new ajax page loads the following script can be used:

<script type="text/javascript">
        var remodalInst = $('.remodal').remodal();
        $(document).on('opened', '.remodal', function () {
            remodalInst.reload();
        });
</script>

Append this to the end of your remodal.js file to allow the script to work (below the document ready script and above the closing }); :

//Reinitialisation script for workaround with Jquery by oBWolfstar
  //Please visit (https://github.com/VodkaBears/Remodal/issues/257) for more information
   Remodal.prototype.reload = function() {

    // data-remodal-target opens a modal window with the special Id
    $(document).on('click', '[data-' + PLUGIN_NAME + '-target]', function(e) {
      e.preventDefault();

      var elem = e.currentTarget;
      var id = elem.getAttribute('data-' + PLUGIN_NAME + '-target');
      var $target = $('[data-' + PLUGIN_NAME + '-id="' + id + '"]');

      $[PLUGIN_NAME].lookup[$target.data(PLUGIN_NAME)].open();
    });

    // Auto initialization of modal windows
    // They should have the 'remodal' class attribute
    // Also you can write the `data-remodal-options` attribute to pass params into the modal
    $(document).find('.' + NAMESPACE).each(function(i, container) {
      var $container = $(container);
      var options = $container.data(PLUGIN_NAME + '-options');

      if (!options) {
        options = {};
      } else if (typeof options === 'string' || options instanceof String) {
        options = parseOptions(options);
      }

      $container[PLUGIN_NAME](options);
    });

    // Handles the keydown event
    $(document).on('keydown.' + NAMESPACE, function(e) {
      if (current && current.settings.closeOnEscape && current.state === STATES.OPENED && e.keyCode === 27) {
        current.close();
      }
    });

    // Handles the hashchange event
    $(window).on('hashchange.' + NAMESPACE, handleHashChangeEvent);
  };

If a developer wants to push this to the git then that'd be great, i know it's not a fully fledged fix but its working for me.