JSFiddle - React, Tailwind, and code Playground

TinyMCE Accordions

by tonytlwu

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.5.4/tinymce.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div class="container-fluid">
  <div class="row">
    <div class="col-xs-12">
      <h3>Accordion setup <button id="btn" class="btn btn-primary pull-right">Create accordion</button></h3>
      <div id="content">
        <p>Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Donec ullamcorper nulla non metus auctor fringilla. Aenean lacinia bibendum nulla sed consectetur. Nulla vitae elit libero, a pharetra augue. Duis mollis, est non commodo luctus,
          nisi erat porttitor ligula, eget lacinia odio sem nec elit. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Nullam quis risus eget urna mollis ornare vel eu leo.</p>

        <form>
          <div class="form-group">
            <label for="exampleInputEmail1">Email address</label>
            <input type="email" class="form-control" id="exampleInputEmail1" placeholder="Email">
          </div>
          <div class="form-group">
            <label for="exampleInputPassword1">Password</label>
            <input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password">
          </div>
          <div class="form-group">
            <label for="exampleInputFile">File input</label>
            <input type="file" id="exampleInputFile">
            <p class="help-block">Example block-level help text here.</p>
          </div>
          <div class="checkbox">
            <label>
              <input type="checkbox"> Check me out
            </label>
          </div>
          <button type="submit" class="btn btn-default">Submit</button>
        </form>


        <p>Nullam id dolor id nibh...

CSS

img {
  max-width: 100%;
  height: auto;
}

#content {
  margin-top: 80px;
}

#btn {
  position: fixed;
  top: 15px;
  right: 15px;
  z-index: 1;
}

.panel > .panel-heading > .panel-title {
  position: relative;
}

.panel > .panel-heading > .panel-title:after {
  content: '–';
  display: block;
  position: absolute;
  right: 0;
  top: 0;
  line-height: 1;
  margin-top: -1px;
}

.panel > .panel-heading > .panel-title.collapsed:after {
  content: '+';
}

JavaScript

function guid() {
  function s4() {
    return Math.floor((1 + Math.random()) * 0x10000)
      .toString(16)
      .substring(1);
  }
  return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
    s4() + '-' + s4() + s4() + s4();
}

var accordionTemplate = [
  '<div class="panel panel-default" contenteditable="false">',
  '<div class="panel-heading" role="tab">',
  '<h4 class="panel-title" data-toggle="collapse" data-target="#{{id}}" contenteditable="true">',
  '{{title}}',
  '</h4>',
  '</div>',
  '<div id="{{id}}" class="panel-collapse collapse in" role="tabpanel">',
  '<div class="panel-body" contenteditable="true">',
  '{{{body}}}',
  '</div>',
  '</div>',
  '</div>',
].join('');

var ACCORDION_DEFAULT = {
  title: 'Enter accordion title',
  body: '<p>Enter accordion content - fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna.</p>'
};

function onTinyMceChange() {
  verifyAccordionPanels();
  verifyAccordionGroups();
}

function verifyAccordionPanels() {
  var ed = tinymce.activeEditor;
  var range = ed.selection.getRng();
  var $content = $(ed.getBody());
  $content.find('.panel-heading > .panel-title[data-toggle="collapse"][data-target]').each(function() {
    var $titleToggle = $(this);
    if ($titleToggle.parent().next().hasClass('panel-collapse')) {
      // Heading has a panel-collapse next
      // Make sure the IDs are matching
      $titleToggle.parent().next().attr('id', $titleToggle.attr('data-target').match(/#?(.*)/)[1]);
      return;
    }
    console.log('Uh-oh');
    $titleToggle.unwrap();
  });
  $content.find('.panel-collapse[id]').each(function() {
    var $panelCollapse = $(this);
    if ($panelCollapse.prev().children('.panel-title').is('[data-toggle]')) {
      // Panel has matching toggle
      // Make sure the IDs are matching
     ...