0

In some cases jquery .prepend() and .append() insert text instead of DOM objects. To reproduce, run code snippet and press Add group link in detail band. Inserted html appears as text.

Instead of this, bootsrtap panels should appear.

It looks like jQuery prepend and append does not add DOM objects work for unknown reason.

How to fix this so that new panels appear before and after detail panel ?

$(function() {

  var startpos,
    selected = $([]),
    offset = {
      top: 0,
      left: 0
    };

  $('#designer-detail-addband').on('click', function() {
    var $this = $(this),
      $parentpanel = $this.parents(".designer-panel").get(0);

    $parentpanel.prepend('<div class="panel designer-panel">' +
      '<div class="panel-body designer-panel-body" style="height:1px">' +
      '</div>' +
      '<div class="bg-warning">' +
      '<div class="panel-footer"><i class="glyphicon glyphicon-chevron-up">' +
      '</i> Group heade {0}: <span id="band{0}_expr" contenteditable="true">"groupexpression"</span>' +
      '</div></div></div>');

    $parentpanel.append('<div class="panel designer-panel">' +
      '<div class="panel-body designer-panel-body" style="height:1px"></div>' +
      '<div class="bg-warning">' +
      '<div class="panel-footer"><i class="glyphicon glyphicon-chevron-up">' +
      '</i> Group footer {0}' +
      '</div></div></div>');

  });






  $(".designer-panel-body").droppable({
    accept: ".designer-field"
  });

  $(".designer-field").draggable({
    start: function(event, ui) {
      var $this = $(this);
      if ($this.hasClass("ui-selected")) {
        selected = $(".ui-selected").each(function() {
          var el = $(this);
          el.data("offset", el.offset());
        });
      } else {
        selected = $([]);
        $(".designer-field").removeClass("ui-selected");
      }
      offset = $this.offset();
    },

    drag: function(event, ui) {
      // drag all selected elements simultaneously
      var dt = ui.position.top - offset.top,
        dl = ui.position.left - offset.left;
      selected.not(this).each(function() {
        var $this = $(this);
        var elOffset = $this.data("offset");
        $this.css({
          top: elOffset.top + dt,
          left: elOffset.left + dl
        });
      });
    }
  });



  $(".panel-resizable").resizable({
    minWidth: "100%",
    maxWidth: "100%",
    minHeight: 1
  });
});
.panel-resizable {
  min-height: 1px;
  overflow: hidden;
  margin: 0;
  padding: 0;
}
.designer-field {
  border: 1px solid lightgray;
  white-space: pre;
  overflow: hidden;
  position: absolute;
}
.designer-panel-body {
  min-height: 1px;
  overflow: hidden;
  margin: 0;
  padding: 0;
}
.panel-footer {
  padding: 0;
}
.designer-panel,
.panel-body {
  margin: 0;
  padding: 0;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="http://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
</head>

<body>
  <div class='panel designer-panel'>
    <div class='panel-body designer-panel-body panel-resizable' style='height:2cm'>

      <div class='designer-field' style='left:5px;top:6px;width:180px'>field 1 in group 1 header</div>

      <div class='designer-field' style='left:54px;top :36px;width:160px'>field 2 in group 1 header</div>
    </div>

    <div class='panel-footer'>Group 1 Header</div>
  </div>

  <div class='panel designer-panel'>
    <div class='panel-body panel-resizable' style='height:1cm'>
      <div class='designer-field' style='left:24px;top:2px;width:140px'>field in detail group</div>
    </div>
    <div class='panel-footer panel-primary'>Detail <a role="button" id="designer-detail-addband"> Add group</a>
    </div>
  </div>

  <div class='panel'>
    <div class='panel-body panel-resizable' style='height:1cm'>

      <div class='designer-field' style='left:44px;top:2px;width:140px'>field in group 1 footer</div>
    </div>
    <div class='panel-footer panel-warning'>Group 1 Footer</div>
  </div>
Rajesh
  • 24,354
  • 5
  • 48
  • 79
Andrus
  • 26,339
  • 60
  • 204
  • 378

1 Answers1

1

.get returns a HTMLElement. That is why, its appending string.

If you wish to select first element, you should use :first selector.

$parentpanel = $this.parents(".designer-panel:first");

$(function() {

  var startpos,
    selected = $([]),
    offset = {
      top: 0,
      left: 0
    };

  $('#designer-detail-addband').on('click', function() {
    var $this = $(this),
      $parentpanel = $this.parents(".designer-panel:first");

    $parentpanel.prepend('<div class="panel designer-panel">' +
      '<div class="panel-body designer-panel-body" style="height:1px">' +
      '</div>' +
      '<div class="bg-warning">' +
      '<div class="panel-footer"><i class="glyphicon glyphicon-chevron-up">' +
      '</i> Group heade {0}: <span id="band{0}_expr" contenteditable="true">"groupexpression"</span>' +
      '</div></div></div>');

    $parentpanel.append('<div class="panel designer-panel">' +
      '<div class="panel-body designer-panel-body" style="height:1px"></div>' +
      '<div class="bg-warning">' +
      '<div class="panel-footer"><i class="glyphicon glyphicon-chevron-up">' +
      '</i> Group footer {0}' +
      '</div></div></div>');

  });

  $(".designer-panel-body").droppable({
    accept: ".designer-field"
  });

  $(".designer-field").draggable({
    start: function(event, ui) {
      var $this = $(this);
      if ($this.hasClass("ui-selected")) {
        selected = $(".ui-selected").each(function() {
          var el = $(this);
          el.data("offset", el.offset());
        });
      } else {
        selected = $([]);
        $(".designer-field").removeClass("ui-selected");
      }
      offset = $this.offset();
    },

    drag: function(event, ui) {
      // drag all selected elements simultaneously
      var dt = ui.position.top - offset.top,
        dl = ui.position.left - offset.left;
      selected.not(this).each(function() {
        var $this = $(this);
        var elOffset = $this.data("offset");
        $this.css({
          top: elOffset.top + dt,
          left: elOffset.left + dl
        });
      });
    }
  });

  $(".panel-resizable").resizable({
    minWidth: "100%",
    maxWidth: "100%",
    minHeight: 1
  });
})
.panel-resizable {
  min-height: 1px;
  overflow: hidden;
  margin: 0;
  padding: 0;
}
.designer-field {
  border: 1px solid lightgray;
  white-space: pre;
  overflow: hidden;
  position: absolute;
}
.designer-panel-body {
  min-height: 1px;
  overflow: hidden;
  margin: 0;
  padding: 0;
}
.panel-footer {
  padding: 0;
}
.designer-panel,
.panel-body {
  margin: 0;
  padding: 0;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<link rel="stylesheet" href="http://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="http://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
</head>

<body>
  <div class='panel designer-panel'>
    <div class='panel-body designer-panel-body panel-resizable' style='height:2cm'>

      <div class='designer-field' style='left:5px;top:6px;width:180px'>field 1 in group 1 header</div>

      <div class='designer-field' style='left:54px;top :36px;width:160px'>field 2 in group 1 header</div>
    </div>

    <div class='panel-footer'>Group 1 Header</div>
  </div>

  <div class='panel designer-panel'>
    <div class='panel-body panel-resizable' style='height:1cm'>
      <div class='designer-field' style='left:24px;top:2px;width:140px'>field in detail group</div>
    </div>
    <div class='panel-footer panel-primary'>Detail <a role="button" id="designer-detail-addband"> Add group</a>
    </div>
  </div>

  <div class='panel'>
    <div class='panel-body panel-resizable' style='height:1cm'>

      <div class='designer-field' style='left:44px;top:2px;width:140px'>field in group 1 footer</div>
    </div>
    <div class='panel-footer panel-warning'>Group 1 Footer</div>
  </div>

It uses ParentNode.prepend instead. Reference

Andrus
  • 26,339
  • 60
  • 204
  • 378
Rajesh
  • 24,354
  • 5
  • 48
  • 79
  • There are also [`.first()`](https://api.jquery.com/first/) and [`.eq(0)`](https://api.jquery.com/eq/). – Ouroborus Oct 30 '16 at 07:20
  • Reference wrote that `ParentNode.prepend` is not supported in Android browser. My applicaton should run in android mobiles also, so it looks like this cannot used – Andrus Oct 30 '16 at 07:22
  • @Ouroborus I have always found lines blur between `:first` and `.first`. I assume, `:first` is a css selector and `.first` is a jQuery wrapper. [Reference](http://stackoverflow.com/questions/2312761/jquery-first-vs-first) – Rajesh Oct 30 '16 at 07:23
  • @Andrus No. If you scroll down on that page, you will see a browser compatibility section. Also your initial code was using it. So if you switch to jQuery function, you should not bother compatibility. jQuery takes care of it – Rajesh Oct 30 '16 at 07:25
  • 1
    @Rajesh That's true. The difference mainly gets into how stuff works. `:first` isn't a real CSS selector in that it's not in the specs and browsers don't support it natively. This means, for jQuery, there's overhead involving detecting it's use, restructuring the selector to not use it, then processing the results to take it into account. This is only important, though, if it's being applied frequently (in a loop, for example). – Ouroborus Oct 30 '16 at 07:29
  • @Rajesh Code in answer adds new panels as `child elements` to Detail pane. Second Add band click does not add new panels immediately before and after detail panel. How to add new panels before and after Detail panel in same level like exisiting header and footer bands in sample html ? – Andrus Oct 30 '16 at 18:14
  • Apologies. It's getting late and I'm going to sleep. I'll update my answer tomorrow. Just put a comment of what is required. – Rajesh Oct 30 '16 at 18:18
  • @Rajesh I put this as separate question in http://stackoverflow.com/questions/40332193/how-to-add-new-panels-before-and-after-clicked-panel – Andrus Oct 30 '16 at 18:27
  • @Rahesh. How to make headers sortable in this code ? I posted it in http://stackoverflow.com/questions/40333881/how-to-make-header-panels-sortable – Andrus Oct 30 '16 at 21:42