0

I have a very simple calendar. When clicking any date a jQuery dialog gets opened, the user clicks a button, the dialog closes, the clicked button's value gets appended to the clicked element and after that all clicked elements get saved to an array.

I have created a JSBin.

html:

<!DOCTYPE html>
<html>
    <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>JS Bin</title>
    </head>
    <body>
        <a href="#" id="2016-11-01" class="cal_clean_active">Click me</a>
        <div id="dialog"></div>
        <link href="https://code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css" rel="stylesheet" type="text/css" />
         <script src="https://code.jquery.com/jquery-3.1.0.js"></script>
         <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>  
    </body>
    </html>

js:

$('.cal_clean_active').click(function(e) {
  var that = $(this); 
  var dates = new Array();

  that.toggleClass('clicked');

  $('#dialog').dialog({
    resizable: false,
    height: "auto",
    width: "auto",
    modal: true,
    buttons: {
      "Vormittags (bis 12:00 Uhr)": function() {
        that.attr('slot','vormittags');
        console.log(that.attr('slot'));
        $(this).dialog('close');
      }
    },
    beforeClose: function() {
      $('.clicked').each(function(i, val) { 
        dates.push(val.id + '|' + val.slot);
      });
        console.log(dates);
    }
  });
});

In Chrome everything works as expected (Console output is 2016-11-01|vormittags) in every other tested Browser (Firefox, Edge, IE) the console output is 2016-11-01|undefined. Any help would be appreciated.

mazedlx
  • 1,405
  • 17
  • 24
  • 1
    Can you try `$(val).attr("slot")`? – JohannesB Nov 18 '16 at 09:17
  • Thanks, that seems to do the job. I still don't understand why I can't access the property `slot` like I can access the propery `id`. – mazedlx Nov 18 '16 at 09:22
  • Slot is not a standard property for an element as far as I know, so it is not standard included in the property list of an element in most browsers. In this case it would probably be cleaner to use the jQuery [.data()](https://api.jquery.com/jquery.data/) handler though. – JohannesB Nov 18 '16 at 09:26
  • Please post your comment as answer so I can vote it as the answer to the question. – mazedlx Nov 18 '16 at 09:28

1 Answers1

1

The problem is that slot is not a standard attribute for an element. In most browsers, it is hence not included in the standard properties of an element (like element.value or element.id). Chrome seems to handle this situation differently than the other browsers.

Two bad solutions

A solution would be to change:

dates.push(val.id + '|' + val.slot);

to

dates.push(val.id + '|' + $(val).attr('slot'));`. 

Another - plain javascript - solution could be to use the javascript getAttribute() method. This would work because in the jQuery source code custom attributes are set with this line:

elem.setAttribute( name, value + "" ); //from the jQuery source code

Thus making it possible to also read them with element.getAttribute(). Your line would then look like this:

dates.push(val.id + '|' + val.getAttribute("slot"));

The better solution

This might all work, but it still is not considered good code. In your code the attribute slot is used to store data. From the .data() jQuery docs (see this answer):

Store arbitrary data associated with the specified element. Returns the value that was set.

$.attr() on the contrary is used to manipulate attributes, like id, value or type. The clean way of solving this problem would be:

$('.cal_clean_active').click(function(e) {
  var that = $(this); 
  var dates = new Array();

  that.toggleClass('clicked');

  $('#dialog').dialog({
    resizable: false,
    height: "auto",
    width: "auto",
    modal: true,
    buttons: {
      "Vormittags (bis 12:00 Uhr)": function() {
        that.data('slot','vormittags'); //Not the use of data
        console.log(that.data('slot'));
        $(this).dialog('close');
      }
    },
    beforeClose: function() {
      $('.clicked').each(function(i, val) { 
        dates.push(val.id + '|' + $(val).data("slot")); //Also note it here
      });
        console.log(dates);
    }
  });
});
Community
  • 1
  • 1
JohannesB
  • 1,995
  • 21
  • 35