0

I am struggling to get a jquery datepicker to work within a custom polymer element. It seems to bind to the body instead of the element itself, for example:

<polymer-element
  name="test-datepicker">
  <template>
      <p>Date: <input type="text" id="dp"></p>
  </template>
</polymer-element>

with the definition:

Polymer('test-datepicker', {

    ready: function() {
        $(this.$.dp).datepicker();
    },
});

... results in the pop-up calendar displaying at the top of the page instead of under the input as it would otherwise, as you can see in the running example over at jsbin: http://jsbin.com/saqojihi/1/

I'm having similar issues with bootstrap tooltips not displaying if they overlap the edges of a web component, and I'm hoping these two are related.

Is there another way that I should be calling the datepicker? I've tried direct references, $("#id").datepicker(), but as it says in another ticket, jquery "doesn't know about ShadowDOM". I've also tried using the lightdom attribute to no avail.

I'm hoping someone has had success with this.

Edit: 4/4/14

Thanks to @Scott Miles for the suggestion, I've added the following override of JQuery.contains, but this probably still isn't the ideal solution:

$(function(){
  // Store a reference to the original contains method.
  var originalContains = jQuery.contains;
  jQuery.contains = function(parent, child){
      var re = /datepicker|dp/i;
      if(child.className.match(re)) {
        return true;
      }
      // Execute the original method.
      return originalContains.apply( this, arguments );
  }
});

It works for now, but I'll have to see how it plays out in a more complete app.

Community
  • 1
  • 1
jamstooks
  • 1,425
  • 2
  • 14
  • 22

1 Answers1

3

In this particular case, the problem boils down to the notion of what document.contains returns wrt elements in ShadowDOM (https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141).

The datepicker positioning code is written to ignore elements not contained by document. The <input> is currently not considered contained, so the positioning code aborts.

I was able to hack a solution by simply stubbing out JQuery's contains code like this:

$(function() {
  jQuery.contains = function() {
    return true;
  };
 });

This is clearly a workaround (bad) solution, but it makes the JsBin work for now.

http://jsbin.com/saqojihi/8/edit

Scott Miles
  • 11,025
  • 27
  • 32
  • Thanks, that's interesting. Obviously, that could have some negative consequences, but I have limited them a bit by modifying your idea a bit: ` $(function(){ var originalContains = jQuery.contains; jQuery.contains = function(parent, child){ var re = /datepicker|dp/i; if(child.className.match(re)) { return true; } return originalContains.apply( this, arguments ); } });` and it looks like [it works](http://jsbin.com/saqojihi/10)! – jamstooks Apr 04 '14 at 17:57
  • I've added the formatted code to my original question in an edit. If it ends up working in my whole app then I'll mark this as the answer. – jamstooks Apr 04 '14 at 18:12
  • Yes I should have been clearer that there is a world of improvements one would do here, specifically replacing `contains` with a ShadowDOM aware implementation would be closer to ideal. The core problem is still that the specifications are unsettled on the question of what the DOM api means, that's going to slow down a complete solution. – Scott Miles Apr 04 '14 at 19:34
  • Thanks. Yeah, until that point, I think one-off solutions like this will have to do. Much appreciated! – jamstooks Apr 04 '14 at 21:22