Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

HTML Settings

Here you can Sed posuere consectetur est at lobortis. Donec ullamcorper nulla non metus auctor fringilla. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.

            
              <div class="widget" id="widget" data-widget="code">
	<div class="widget-tab-list">
		<div class="widget-tab tab-active" data-tab="0">
			<label class="tab-text">main<span>.js</span></label>
			<div class="tab-delete"></div>
		</div>
		<div class="widget-tab" data-tab="1">
			<label class="tab-text">main<span>.html</span></label>
			<div class="tab-delete"></div>
		</div>
		<div class="widget-tab" data-tab="2">
			<label class="tab-text">main<span>.css</span></label>
			<div class="tab-delete"></div>
		</div>
		<div class="add-tab"></div>
	</div>
	<div class="widget-inner panel-active" data-inner="0">
		<div class="new-inner" data-language="js" data-tag="script"> 
			<textarea class="editor" style="display: none;">var str = "Hello, World!";
console.log("hello, there!");
$(document).on('click', '.btn', function() {
  $(this).toggleClass('active');
});</textarea> 
			<div class="CodeMirror-vscrollbar-filler"></div> 
			<div class="CodeMirror-hscrollbar-filler"></div> 
		</div>
	</div>
	<div class="widget-inner" data-inner="1">
		<div class="new-inner" data-language="html" data-tag="wrapper"> 
			<textarea class="editor" style="display: none;"><div class="col-sm-12">
  <div class="row">
	<div class="col-sm-4">
	  <button class="btn btn-sm btn-primary">one</button>
	</div>
	<div class="col-sm-4">
		<button class="btn btn-sm btn-secondary">two</button>
	</div>
	<div class="col-sm-4">
		<button class="btn btn-sm btn-default">two</button>
	</div>
  </div>
</div></textarea> 
			<div class="CodeMirror-vscrollbar-filler"></div> 
			<div class="CodeMirror-hscrollbar-filler"></div> 
		</div>
	</div>
	<div class="widget-inner" data-inner="2">
		<div class="new-inner" data-language="css" data-tag="style"> 
			<textarea class="editor" style="display: none;">body { background: #fff; } .active { background: purple !important; }
			</textarea> 
			<div class="CodeMirror-vscrollbar-filler"></div> 
			<div class="CodeMirror-hscrollbar-filler"></div> 
		</div>
	</div>
	<div class="preview">
		<div class="resize-handle"></div>
		<iframe></iframe>
	</div>
</div>

<div class="modal" tabindex="-1" role="dialog">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">File Name</h5>
        <div class="modal-close" data-dismiss="modal" aria-label="Close">
        </div>
      </div>
      <div class="modal-body">
				<div class="form-group">
					<label class="info-labels">File name:</label>
					<input type="text" class="file-name-input">
					<label class="tab-type">.js</label>
				</div>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn modal-close-btn" data-dismiss="modal">Close</button>
        <button type="button" class="btn modal-save">Save changes</button>
      </div>
    </div>
  </div>
</div>
<div class="loader-div">
	<ul class="loader-list">
		<li class="loader-item"></li>
		<li class="loader-item"></li>
		<li class="loader-item"></li>
		<li class="loader-item"></li>
		<li class="loader-item"></li>
	</ul>
</div>
<div class="tutorial-div"></div>

<div class="modal-code-callout" tabindex="-1" role="dialog">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Callout Dialog</h5>
        <div class="modal-close" data-dismiss="modal" aria-label="Close">
        </div>
      </div>
      <div class="modal-body">
				<div class="form-group">
					<label class="info-labels">Callout Dialog: </label>
					<input type="text" class="callout-dialog-input">
				</div>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn modal-close-btn" data-dismiss="modal">Close</button>
        <button type="button" class="btn modal-save">Save changes</button>
      </div>
    </div>
  </div>
</div>

<button class="goto"><a href="https://codepen.io/Souleste/pen/RXebxO" target="_blank">Custom Theme</a></button>

            
          
!
            
              body {
	background: #000;
}
.widget {
	width: 600px;
	max-width: 600px;
	height: fit-content;
	display: inline-block;
	margin-bottom: 25px;
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%,-50%);
}
.widget-inner {
	height: 200px;
	max-height: 400px;
	position: relative;
}
.widget-inner .new-inner {
	position: absolute;
	top: 40px;
	bottom: 0;
	width: 100%;
}
.widget-inner .ui-resizable-handle {
	height: 15px;
	background: #333359;
	position: absolute;
	bottom: 0;
	left: 0;
	right: 0;
	z-index: 5;
	cursor: n-resize;
}
.preview {
	width: 100%;
	height: 200px;
	border-radius: 0 0 5px 5px;
	position: relative;
	min-height: 100px;
}
.preview iframe {
	border: 2px solid #333359;
	border-radius: 0 0 5px 5px;
	width: 100%;
	height: 100%;
}
.widget-tab-list {
	height: 30px;
	padding: 0px 30px;
	position: relative;
}
.widget-tab {
	min-width: 50px;
	width: fit-content;
	height: 100%;
	background: #111139;
	border-bottom: 0;
	border-radius: 5px 5px 0 0;
	padding: 2px 35px 5px 10px;
	margin: 0 5px 0 0;
	position: relative;
	color: #ddddff;
	cursor: pointer;
	display: inline-block;
	float: left;
}
.tab-active {
	background: #333359;
}
.tab-text {
	pointer-events: none;
}
.tab-delete {
	width: 20px;
	height: 20px;
	background: #111139;
	position: absolute;
	top: 6px;
	right: 5px;
	border-radius: 50%;
	cursor: pointer;
}
.tab-delete::after {
	font-family: 'Font Awesome 5 Free';
  font-weight: 800;
	content: "\f00d";
	display: inline-block;
	z-index: 1;
	position: absolute;
	top: 50%;
	left: 48%;
	transform: translate(-50%,-50%);
	font-size: 12px;
	color: #55555f;
	pointer-events: none;
}
.add-tab {
	width: 20px;
	height: 20px;
	background: #333359;
	position: absolute;
	top: 5px;
	left: 5px;
	border-radius: 50%;
	cursor: pointer;
}
.add-tab::after {
	font-family: 'Font Awesome 5 Free';
  font-weight: 800;
	content: "\f067";
	display: inline-block;
	z-index: 1;
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%,-50%);
	font-size: 11px;
	color: #ddddff;
	pointer-events: none;
}
.widget-inner {
	display: none;
}
.panel-active {
	display: block;
}
.widget-settings {
	background: #333359;
	border-radius: 5px 5px 0 0;
	height: 40px;
	position: relative;
}
.code-mode, .read-only {
	background: #222249;
	border: 0;
	height: 30px;
	width: 200px;
	display: inline-block;
	margin: 5px 0 0 30px;
	color: #eee;
	cursor: pointer;
	border-radius: 4px;
}
.code-mode:focus, .read-only:focus {
	background: #222249;
	outline: none !important;
	color: #eee;
}
.code-mode option {
	border: 0;
}
.code-mode-wrap {
	width: fit-content;
	margin: 0;
	display: inline;
	position: relative;
}
.code-mode-wrap::before {
	content: '';
	width: 20px;
	height: 20px;
	background: #222249;
	position: absolute;
	right: 5px;
	top: 1px;
	pointer-events: none;
}
.code-mode-wrap::after {
	font-family: 'Font Awesome 5 Free';
	content: '\f013';
	font-weight: 800;
	font-size: 15px;
	color: #ddddff;
	position: absolute;
	top: 1px;
	right: 15px;
	pointer-events: none;
	transition: 0.3s;
}
.remove-widget {
	width: 29px;
	height: 29px;
/* 	background: #eee; */
	position: absolute;
	right: 21px;
	top: 6px;
	border-radius: 50%;
	background: #111139;
	cursor: pointer;
}
.remove-widget::after {
	font-family: 'Font Awesome 5 Free';
	content: '\f00d';
	font-weight: 800;
	font-size: 15px;
	color: #eee;
	position: absolute;
	top: 4px;
	left: 9px;
}
.add-editor {
	background: #222249;
	color: #ddddff;
	border: 0;
	border-radius: 5px;
	padding: 10px 20px;
	margin: 15px 30px;
	cursor: pointer;
}

.edit-tab {
	width: 30px;
	height: 30px;
	background: #111139;
	border-radius: 50%;
	position: absolute;
	top: 5px;
	right: 5px;
	cursor: pointer;
}
.edit-tab::after {
	font-family: 'Font Awesome 5 Free';
  font-weight: 800;
	content: "\f303";
	position: absolute;
	right: 7px;
	top: 5px;
	font-size: 14px;
	color: #ddddff;
	pointer-events: none;
}
.edit-tab::before {
	content: 'edit tab name.';
	background: #111139;
	color: #ccccff;
	min-width: 125px;
	padding: 0px 10px;
	position: absolute;
	left: 40px;
	top: 4px;
	z-index: 100;
	opacity: 0;
	transition: 0.5s;
	transition-delay: 0.5s;
}
.edit-tab:hover::before {
	opacity: 1;
}

.add-callout {
	width: 30px;
	height: 30px;
	background: #111139;
	border-radius: 50%;
	position: absolute;
	top: 5px;
	right: 85px;
	cursor: pointer;
}
.add-callout::after {
	font-family: 'Font Awesome 5 Free';
  font-weight: 800;
	content: "\f05a";
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-45%,-50%);
	font-size: 14px;
	color: #ddddff;
	pointer-events: none;
}
.new-inner {
	border-radius: 0 0 5px 5px;
}
.code-callout {
  display: inline-block;
	width: -webkit-fill-available;
	padding: 0 10px 0 0;
  box-sizing: border-box;
	border-radius: 4px;
	margin-left: 25px;
	font-weight: bold;
}
.code-callout > label {
	width: 30px;
	height: 21px;
	position: absolute;
	top: 0;
	left: 5px;
	cursor: pointer;
}
.code-callout > label::after {
	font-family: 'Font Awesome 5 Free';
  font-weight: 800;
	position: absolute;
	top: 0px;
	left: 0px;
	font-size: 15px;
	pointer-events: none;
}
[data-callout='danger'] {
	color: #db3939;
}
[data-callout='danger'] > label::after {
	content: "\f06a";
}
[data-callout='warning'] {
	color: #e09807;
}
[data-callout='warning'] > label::after {
	content: "\f071";
}
[data-callout='info'] {
	color: #115b9c;
}
[data-callout='info'] > label::after {
	content: "\f05a";
}
[data-callout='good'] {
	color: #3ba31c;
}
[data-callout='good'] > label::after {
	content: "\f058";
}
.code-callout > input {
	color: inherit;
	width: 100%;
	height: 21px;
	background: #fff;
	border: 0;
	font-weight: bold;
	padding-left: 6px;
	border-radius: 3px;
}
.code-callout > input::placeholder {
	color: rgba(0,0,0,0.4);
}
.code-callout > input:focus {
	outline: none !important;
}


.CodeMirror {
	
/* 	height: 200px !important; */
	height: 100%;
	font-size: 14px !important;
}

/********
BOOKMARK
********/
.CodeMirror-code > *:not(.add-bookmark, .bookmark) {
	pointer-events: none !important;
}
.bookmark {
	height: 20px;
	width: 20px;
	position: absolute;
	top: 1px;
	right: -10px;
	z-index: 10;
	cursor: pointer;
}
.bookmark::after {
	font-family: 'Font Awesome 5 Free';
  font-weight: 800;
	content: "\f02e";
	display: inline-block;
	z-index: 1;
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%,-50%);
	font-size: 11px;
	color: #ddddff;
	pointer-events: none;
}
.bookmark::before {
	font-family: 'Font Awesome 5 Free';
	content: '\f00d';
	font-weight: 800;
	font-size: 9px;
	color: #111139;
	position: absolute;
	top: 2px;
	left: 7px;
	z-index: 10;
	opacity: 0;
}
.bookmark:hover::before {
	opacity: 1;
}
.add-bookmark {
	width: 30px;
	height: 30px;
	position: absolute;
	background: #111139;
	border-radius: 50%;
	top: 5px;
	right: 45px;
	z-index: 10;
	cursor: pointer !important;
}
.add-bookmark::after {
	font-family: 'Font Awesome 5 Free';
  font-weight: 800;
	content: "\f02e";
	display: inline-block;
	z-index: 1;
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%,-50%);
	font-size: 11px;
	color: #ddddff;
	pointer-events: none;
}


.markdown-link {
	background: #e8f0fe;
	cursor: pointer;
	padding: 2px 5px;
	border-radius: 3px;
}

/*****
LOADER
*****/

.loader-div {
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	background: #111;
}

.loader-list {
	width: 85px;
	height: 50px;
	padding: 0;
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	list-style-type: none;
}

@-webkit-keyframes 'loadbars' {
	0%{
		height: 10px;
		margin-top: 25px;
	}
	50%{
		height:50px;
		margin-top: 0px;
	}
	100%{
		height: 10px;
		margin-top: 25px;
	}
}

.loader-item {
	background-image: linear-gradient(#f23737, #a31616);
	width: 10px;
	height: 10px;
	float: right;
	margin-right: 6px;
	border-radius: 50px;
	/*box-shadow: 0px 20px 10px rgba(255, 255, 255, 0.1);*/
}
.loader-item:first-child{
	-webkit-animation: loadbars 1s cubic-bezier(0.645,0.045,0.355,1) infinite 0s;
}
.loader-item:nth-child(2){
	-webkit-animation: loadbars 1s ease-in-out infinite -0.2s;
}
.loader-item:nth-child(3){
	-webkit-animation: loadbars 1s ease-in-out infinite -0.4s;
}
.loader-item:nth-child(4){
	-webkit-animation: loadbars 1s ease-in-out infinite -0.6s;
}
.loader-item:nth-child(5){
	-webkit-animation: loadbars 1s ease-in-out infinite -0.8s;
}
.loader-item:nth-child(5){
	-webkit-animation: loadbars 1s ease-in-out infinite -0.8s;
}


/***********
MODAL	
***********/
.modal-code-callout {
	display: none;
}


.goto {
	position: absolute;
	bottom: 10px;
	left: 10px;
	background: #222249;
	border: 5px solid #11112f;
	color: #ddddff;
	padding: 5px 10px;
	border-radius: 5px;
	cursor: pointer;
}
.goto a {
	color: #ddddff;
	display: block;
	height: 100%;
	width: 100%;
}
.goto a:hover {
	text-decoration: none;
}


.CodeMirror-scroll {
	padding-bottom: 10px;
}
            
          
!
            
              $(function() {
	
	$(".loader-div").delay(1000).fadeOut();

	var editorOptions = {
		autoRefresh: true,
		firstLineNumber: 1,
		lineNumbers: true,
		lineWrapping: true,
		smartIndent: true,
		indentWithTabs: true,
		styleActiveLine: { nonEmpty: true },
		matchBrackets: true,
		matchTags: { bothTags: true },
		findMatchingBrackets: true,
		extraKeys: { 
			'Ctrl-M': 'toMatchingTag', 
			'Shift-Ctrl-C': 'toggleComment', 
			'Ctrl-/': 'toggleComment',
		},
		refresh: true,
		viewportMargin: Infinity
	};
	
	var links = `
	<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css"></link>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"><\/script>
	<script id="set_jquery">var $ = parent.$;<\/script>
	`;
	var widget_settings = `<div class="widget-settings"><div class="code-mode-wrap"><select class="form-control form-control-sm code-mode"><option value="js" data-lang="javascript" data-l-sm="js">JavaScript</option><option value="html" data-lang="htmlmixed" data-l-sm="html">HTML</option><option value="css" data-lang="css" data-l-sm="css">CSS</option><option value="php" data-lang="text/x-php" data-l-sm="php">PHP</option></select></div><select class="form-control form-control-sm read-only"><option data-readonly="false" value="false">edit</option><option data-readonly="true" value="true">read-only</option></select><div class="edit-tab"></div><div class="add-bookmark"></div><div class="add-callout"></div></div>`;
	
	var widget_data = [
		{readOnly: false},
		{readOnly: true},
		{readOnly: true}
	];
	
	var modal = $(".modal");
	var count = 0;
	var widget = $(document).find(".widget");
	widget.each(function() {
		var inner = $(this).find(".widget-inner");
		inner.each(function() {
			var self = $(this);
			// prepend the settings: change code mode, switch between readonly / edit mode...
			self.prepend(widget_settings);
			// get the editor
			var editor = CodeMirror.fromTextArea(self.find(".editor")[0], editorOptions);
			self[0].editor = editor;
			console.log(self[0]);
			editor.save();
			
			var codeMode = self.find('.new-inner').attr('data-language');
			var i = self.attr('data-inner');
			
			// beautify the code
			var sampleText = self.find('.editor').text();
			var beautify = eval( (codeMode + '_beautify').toString().toLowerCase() );
			editor.setValue( beautify( sampleText, { indent_size: 2 } ) );
			
			// set readonly / edit mode
			var readOnly = widget_data[i].readOnly;
			self.find('.read-only').val(readOnly.toString());
			editor.setOption('readOnly', readOnly);
			
			// set the code mode
			self.find('.code-mode').val(codeMode);
			var setMode = self.find('.code-mode').find(":selected").attr('data-lang');
			editor.setOption("mode", setMode );
			
			// set minimum number of lines
			var minLines = 10;
			editor.focus();
			editor.setCursor(editor.lineCount(), 0); // Set the cursor at the end of existing content
			var lineCount = editor.lineCount(); // current number of lines
			var n = minLines - lineCount; // how many lines we need
			var line = editor.getCursor().line;
			var ch = editor.getCursor().ch;
			for(i = 0; i < n; i++) {
				editor.replaceRange("\n", { line });
				line++;
			}
			
			editor.on("beforeChange", function(_, change) {
				if (change.origin == "paste") change.cancel()
			});
		});
	});
	
	// update iframe on keyup
	$(document).on('keyup', '.CodeMirror', function() {
		var widget = $(this).closest('.widget');
		var iframe = widget.find('iframe');
		var win = iframe[0].contentWindow;
		var doc = win.document;
		var tagArray = [];
		
		var el = widget.find('.widget-inner');
		el.each(function() {
			var self = $(this);
			var inner = self.find('.new-inner');
			var editor = self[0].editor;
			var i = self.attr('data-inner');
			var type = inner.attr('data-language');
			var content = editor.getValue();
			var tag = inner.attr('data-tag');
			var full = '<'+tag+' id="'+i+'">'+content+'<\/'+tag+'>';
			
			var tagStuff = { 
				i: i,
				type: type,
				content: content,
				tag: tag,
				full: full
			};
			tagArray.push(tagStuff);
		});
		
		doc.open(); doc.close();
		$('head', doc).empty().append(links);
		
		$.each(tagArray, function(index, tagStuff) {
			switch(tagStuff.type) {
				case 'js': $("body", doc).append(tagStuff.full); break;
				case 'css': $("head", doc).append(tagStuff.full); break;
				case 'html': $("body", doc).prepend(tagStuff.full); break;
			}
		});
		
	});
	function setIframe() {
		var widget = $('.widget');
		var iframe = widget.find('iframe');
		var head = iframe.contents().find('head'); 
		var body = iframe.contents().find('body');
		
		head.append(links);
		body.append('<div class="wrapper"></div>');
		var wrapper = iframe.contents().find('.wrapper');
		
		widget.each(function() {
			var inner = $(this).find('.widget-inner');
			inner.each(function() {
				var self = $(this);
				var editor = self[0].editor;
				var data = self.find('.new-inner').attr('data-language');
				var i = self.attr('data-inner');
				// for each editor, we will add the corresponding tag, html goes in the '.wrapper'
				switch(data) {
					case 'js':
						body.append('<script id="'+i+'">'+editor.getValue()+'<\/script>');
						break;
					case 'html':
						wrapper.html(editor.getValue());
						break;
					case 'css':
						head.append('<style id="'+i+'">'+editor.getValue()+'</style>');
						break;
				}
			});
		});
	} setIframe();

	$(document).on("click", ".add-tab", function() {
		var highest = 0;
		// find the highest tab number, and increase it by one.
		var widget = $(this).closest(".widget");
		widget.find(".widget-tab").each(function() {
			var num = parseInt($(this).attr("data-tab"), 10);
			highest = Math.max(highest, parseFloat(num));
		});
		// append the new tab before the '.add-tab' element
		widget.find(".add-tab").before('<div class="widget-tab" data-tab="'+(highest + 1)+'"><label class="tab-text">new<span>.js</span></label><div class="tab-delete"></div></div>'
			);
		// append the new tab panel, doesn't matter "where" it goes
		var inner = $(
			`<div class="widget-inner" data-inner="` + (highest + 1) + `"> 
				<div class="new-inner" data-language="js" data-tag="script"> 
					<textarea class="editor" style="display: none;"></textarea> 
					<div class="CodeMirror-vscrollbar-filler"></div> 
					<div class="CodeMirror-hscrollbar-filler"></div> 
				</div>
			</div>`
		);
		widget.find('.preview').before(inner);
		inner.prepend(widget_settings);
		
		var editor = CodeMirror.fromTextArea(inner.find(".editor")[0], editorOptions);
		inner[0].editor = editor;
		editor.setOption("mode", 'javascript');
		console.log(inner[0]);
		editor.save();
		
		editor.on("beforeChange", function(_, change) {
			if (change.origin == "paste") change.cancel()
		});
		
		var iframe = widget.find('iframe');
		iframe.contents().find('body').append('<script id="'+ (highest + 1) +'"><\/script>');
	});
	
	$(document).on("change", ".code-mode", function() {
		var widget = $(this).closest('.widget');
		var iframe = widget.find('iframe');
		var inner = $(this).closest(".widget-inner");
		var data = inner.attr('data-inner');
		var tab = widget.find('.widget-tab[data-tab="' + data + '"]');
		var language = $(this).find(":selected").attr("data-lang");
		var lsm = $(this).find(":selected").attr("data-l-sm");
		var editor = inner[0].editor;
		editor.setOption("mode", language);
		console.log(editor);
		
		inner.find('.new-inner').attr('data-language', lsm);
		inner.find(".CodeMirror").attr("data-language", lsm);
		tab.find('span').text('.'+lsm);

		switch(lsm) {
			case 'js':
				inner.find('.new-inner').attr('data-tag', 'script');
				if (iframe.contents().find('[id="'+data+'"]').length > 0) {
					iframe.contents().find('[id="'+data+'"]').replaceWith($('<script id="'+data+'">'+editor.getValue()+'<\/script>'));
					iframe.contents().find('[id="'+data+'"]').detach().appendTo(iframe.contents().find('body'));
				} else {
					iframe.contents().find('body').append($('<script id="'+data+'">' + editor.getValue() + '<\/script>'));
				}
				break;
			case 'css':
				inner.find('.new-inner').attr('data-tag', 'style');
				if (iframe.contents().find('[id="'+data+'"]').length > 0) {
					iframe.contents().find('[id="'+data+'"]').replaceWith($('<style id="'+data+'">' + editor.getValue() + '</style>'));
					iframe.contents().find('[id="'+data+'"]').detach().appendTo(iframe.contents().find('head'));
				} else {
					iframe.contents().find('head').append($('<style id="'+data+'">' + editor.getValue() + '</style>'));
				}
				break;
			case 'html':
				inner.find('.new-inner').attr('data-tag', 'wrapper');
				if (iframe.contents().find('[id="'+data+'"]').length > 0) {
					iframe.contents().find('[id="'+data+'"]').remove();
				} else {
					iframe.contents().find('.wrapper').html( editor.getValue() );
				}
				break;
		}
	});
	$(document).on("change", ".read-only", function() {
		var inner = $(this).closest(".widget-inner");
		var editor = inner[0].editor;
		var readOnly = $(this).find(":selected").attr("data-readonly");
		var bool = $.parseJSON(readOnly);
		
		editor.setOption("readOnly", bool);
		inner.find('.code-callout input').attr('disabled', bool);
	});

	// switch tabs
	$(document).on("click", ".widget-tab", function() {
		var tab = $(this);
		var data = tab.attr("data-tab");
		var panel = tab.closest(".widget").find('.widget-inner[data-inner="' + data + '"]');
		if (!tab.hasClass("tab-active")) {
			tab.siblings().removeClass("tab-active");
			tab.addClass("tab-active");
			panel.siblings(".widget-inner").removeClass("panel-active");
			panel.addClass("panel-active");
		}
	});

	// remove tab
	$(document).on("click", ".tab-delete", function() {
		var tab = $(this).closest(".widget-tab");
		var widget = tab.closest(".widget");
		var iframe = widget.find('iframe');
		var data = tab.attr("data-tab");
		var lsm = widget.find('.widget-inner[data-inner="' + data + '"]').find('.new-inner').attr('data-language');
		var panel = widget.find('.widget-inner[data-inner="' + data + '"]');
		if (widget.find(".widget-tab").length > 1) {
			if (tab.hasClass("tab-active")) {
				tab.remove();
				panel.remove();
				widget.find(".widget-tab:first").addClass("tab-active");
				var newData = widget.find(".widget-tab:first").attr("data-tab");
				var newPanel = widget.find('.widget-inner[data-inner="' + newData + '"]');
				newPanel.addClass("panel-active");
			} else {
				tab.remove();
				panel.remove();
				newPanel.addClass("panel-active");
			}
		}
		// remove corresponding iframe tag
		iframe.contents().find('[id="'+data+'"]').remove();
		if (lsm == 'html') {
			console.log('true');
			// we will just empty the body wrapper
			iframe.contents().find('wrapper').empty();
		}
	});

	// edit tab name
	var tabText = null;
	$(document).on("click", ".edit-tab", function() {
		var widget = $(this).closest(".widget");
		var active = widget.find(".panel-active");
		var data = active.attr("data-inner");
		var tab = widget.find('.widget-tab[data-tab="' + data + '"]');
		tabText = tab.find(".tab-text");
		// modal
		var lang = active.find(".new-inner").attr("data-language");
		var type = modal.find(".tab-type");
		type.html("." + lang);
		modal.show();
		$(document).on("click", ".modal-save", function() {
			var newName = modal.find(".file-name-input").val();
			tabText.html(newName + '<span>.'+lang+'</span>');
			modal.hide();
		});
	});

	$(document).on("click", ".modal-close-btn", function() {
		modal.hide();
	});

	// to matching bracket end
	$(document).on("keydown", ".CodeMirror", function(e) {
		var inner = $(this).closest(".widget-inner");
		var editor = inner[0].editor;
		var Pos = CodeMirror.Pos;
		if ( (e.metaKey || e.ctrlKey) && String.fromCharCode(e.which).toLowerCase() === "m" ) {
			editor.extendSelectionsBy(function(range) {
				var next = editor.scanForBracket(range.head, 1);
				if (next && CodeMirror.cmpPos(next.pos, range.head) != 0) {
					return next.pos;
				} else {
					var prev = editor.scanForBracket(range.head, -1);
					return prev && Pos(prev.pos.line, prev.pos.ch + 1) || range.head;
				}
			});
		}
		if ( (e.metaKey || e.ctrlKey) && e.which == 13 ) {
			var mode = inner.find('.new-inner').attr('data-language');
			var text = editor.getValue();
			var beautify = eval( (mode + '_beautify').toString().toLowerCase() );
			editor.setValue( beautify( text, { indent_size: 2 } ) );
		}
	});
	
	// append a bookmark to the line
	$(document).on("mousedown", ".add-bookmark", function() {
		var inner = $(this).closest(".widget-inner");
		var editor = inner[0].editor;
		var cmWidget = document.createElement("span");
		var line = editor.getCursor();
		cmWidget.className = "bookmark";
		editor.setBookmark(editor.getCursor(), cmWidget, true);
	});
	$(document).on("click", ".bookmark", function() {
		var bookmark = $(this);
		bookmark.remove();
	});

	$(document).on("mousedown", ".add-callout", function() {
		var inner = $(this).closest(".widget-inner");
		var editor = inner[0].editor;
		
		var el = $('<div class="code-callout" data-callout="danger"><input type="text" placeholder="type something..."/><label></label></div>')[0];
		
		var line = editor.getCursor().line;
		var ch = editor.getCursor().ch;
		var isEmptyLine = editor.getLine(line).trim() === "";
		if (isEmptyLine) {
			// if line is empty we insert the widget here
			editor.replaceRange(' ', { line });
		} else if (ch === 0) {
			// if character position is zero, don't do anything
			editor.replaceRange(' ' + "\n", pos);
		} else {
			// if line has content, insert widget on new line+
			editor.replaceRange("\n" + ' ', { line });
			line++;
		}
		var widget = editor.markText({ line, ch: 0 }, { line, ch: 1 }, {
			replacedWith: el
		});
		editor.focus();
	});
	
	$(document).on('click', '.code-callout > label', function() {
		var inner = $(this).closest('.widget-inner');
		var editor = inner[0].editor;
		if (editor.options.readOnly == false) {
			var parent = $(this).closest('.code-callout');
			var data = parent.attr('data-callout');
			switch(data) {
				case 'danger':
					parent.attr('data-callout', 'warning');
					break;
				case 'warning':
					parent.attr('data-callout', 'info');
					break;
				case 'info':
					parent.attr('data-callout', 'good');
					break;
				case 'good':
					parent.attr('data-callout', 'danger');
					break;
			}
		}
	});
	
	
	$('.widget-inner').resizable({
		handles: "s",
		resize: function(event, ui) {
			var sibs = $(this).siblings('.widget-inner');
			sibs.height( $(this).height() );
			// var parent = $(this).closest('.widget');
			// var self = $(this);
			// var editor = parent.find('.CodeMirror');
			// editor.height( parent.height() - self.height() ); 
		}
	});
	
	$(document).on('paste', '.CodeMirror', function(e) {
		e.preventDefault();
		var inner = $(this).closest('.widget-inner');
		var editor = inner[0].editor;
		navigator.clipboard.readText().then(text => {
			if (text.match(/^(http:\/\/|https:\/\/)(.*)/g)) {
				var newText = text;
				console.log('trueeeee');
				var el = $('<a class="markdown-link" href="'+newText+'" target="_blank">'+newText+'</a>')[0];
				var line = editor.getCursor().line;
				var ch = editor.getCursor().ch;
				var isEmptyLine = editor.getLine(line).trim() === "";
				if (isEmptyLine) {
					// if line is empty we insert the widget here
					editor.replaceRange(' ', { line });
				} else if (ch === 0) {
					// if character position is zero, don't do anything
					editor.replaceRange(' ' + "\n", pos);
				} else {
					// if line has content, insert widget on new line
					editor.replaceRange("\n" + ' ', { line });
					line++;
				}
				var widget = editor.markText({ line, ch: 0 }, { line, ch: 1 }, {
					replacedWith: el
				});
				editor.focus();
			} else {
				document.execCommand('insertText', false, text);
			}
		});
	});
	
});

            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.

Console