Chrome extension:How to store data locally? - javascript

I tried to do very basic to do list chrome extension.
When i append the value from textarea, it is shown on extension but if i close the extension and then click it , appended value is not there.
How can i store it?
// chrome.tabs.getSelected(null, function(tab){
$("#button").click(function() {
var userList = $('#textarea').val();
localStorage.setItem('userlist', 'userlist');
$('#textarea').val('');
$('#list').append('<p>' + localStorage.getItem('userlist', 'userlist'));
});
// });
#textarea {
display: inline-block;
min-width: 200px;
resize: none;
outline: none;
}
#button {
border: none;
color: #fff;
background: #333;
height: 24px;
width: 50px;
display: inline-block;
vertical-align: 7px;
}
#list {
border: 1px solid #333;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea rows="1" id="textarea"></textarea>
<button id="button">Add</button>
<div id="list"></div>

Have you tried localStorage?
localStorage.setItem('myCat', 'Tom');

Yes. The answer is localStorage.
Basically you can use like this > localStorage.setItem('myCat', 'Tom');
Here below you can see how did i use it.
// just created a list variable where i append my values.
// and then set the list to localStorage.
// then just wrote if statement to check if we have something on local storage already saved.
//all codes here
// chrome.tabs.getSelected(null, function(tab){
$("#button").click(function() {
var userList = $('#textarea').val();
$('#textarea').val('');
$('#list').append('<p>' + userList);
var list = $("#list").html();
localStorage.setItem('list', list);
return false;
});
if (localStorage.getItem('list')) {
$('#list').html(localStorage.getItem('list'));
}
// });
#textarea {
display: inline-block;
min-width: 200px;
resize: none;
outline: none;
}
#button {
border: none;
color: #fff;
background: #333;
height: 24px;
width: 50px;
display: inline-block;
vertical-align: 7px;
}
#list {
border: 1px solid #333;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea rows="1" id="textarea"></textarea>
<button id="button">Add</button>
<div id="list"></div>

Related

A Notepad that keep the notes written even after refresh

I have just found a set of codes that fits my need right now for my blog.
Here I'll attach the code and a glimpse of what it looks like. Although It's still very simple.
What I want to ask is if it's possible to tweak these code possible using JS localstorage, so that it will keep all the saved text even after the user refresh the page, or even better if it stays there even after a user closed the window and reopened it later?
Here's what it looks like right now
and here is the code:
$(document).ready(function(){
var noteCount = 0;
var activeNote = null;
$('.color-box').click(function(){
var color = $(this).css('background-color');
$('notepad').css('background-color', color);
$('#title-field').css('background-color', color);
$('#body-field').css('background-color', color);
})
$('#btn-save').click(function(){
var title = $('#title-field').val();
var body = $('#body-field').val();
if (title === '' && body === '') {
alert ('Please add a title or body to your note.');
return;
}
var created = new Date();
var color = $('notepad').css('background-color');
var id = noteCount + 1;
if (activeNote) {
$('#' + activeNote)[0].children[0].innerHTML = title;
$('#' + activeNote)[0].children[1].innerHTML = created.toLocaleString("en-US");
$('#' + activeNote)[0].children[2].innerHTML = body;
$('#' + activeNote)[0].style.backgroundColor = color;
activeNote = null;
$('#edit-mode').removeClass('display').addClass('no-display');
} else {
var created = new Date();
$('#listed').append('<div id="note' + id + '" style="background-color: ' + color + '"><div class="list-title">' + title + '</div> <div class="list-date">' + created.toLocaleString("en-US") + '</div> <div class="list-text">' + body + '</div> </div>');
noteCount++;
};
$('#title-field').val('');
$('#body-field').val('');
$('notepad').css('background-color', 'white');
$('#title-field').css('background-color', 'white');
$('#body-field').css('background-color', 'white');
});
$('#btn-delete').click(function(){
if (activeNote) {
$('#' + activeNote)[0].remove();
activeNote = null;
$('#edit-mode').removeClass('display').addClass('no-display');
}
$('#title-field').val('');
$('#body-field').val('');
$('notepad').css('background-color', 'white');
$('#title-field').css('background-color', 'white');
$('#body-field').css('background-color', 'white');
});
$('#listed').click(function(e){
var id = e.target.parentElement.id;
var color = e.target.parentElement.style.backgroundColor;
activeNote = id;
$('#edit-mode').removeClass('no-display').addClass('display');
var titleSel = $('#' + id)[0].children[0].innerHTML;
var bodySel = $('#' + id)[0].children[2].innerHTML;
$('#title-field').val(titleSel);
$('#body-field').val(bodySel);
$('notepad').css('background-color', color);
$('#title-field').css('background-color', color);
$('#body-field').css('background-color', color);
})
})
header {
text-align: left;
font-weight: 800;
font-size: 28px;
border-bottom: solid 3px #DEDEDE;
display: flex;
justify-content: space-between;
}
footer {
display: flex;
flex-flow: row-reverse;
padding: 5px 20px;
}
.headers {
margin-top: 20px;
margin-bottom: -10px;
font-size: 20px;
}
#list-head {
margin-left: 2.5%;
width: 30.5%;
display: inline-block;
text-align: center;
}
#note-head {
width: 60%;
margin-left: 5%;
display: inline-block;
text-align: center;
}
noteList {
margin-top: 20px;
display: inline-block;
margin-left: 2.5%;
width: 30.5%;
height: 400px;
overflow: scroll;
border: solid 3px #929292;
border-radius: 5px;
background-color: #DEDEDE;
}
.within-list {
cursor: pointer;
}
.list-title {
font-weight: 600;
font-size: 20px;
padding: 5px 5px 0 5px;
}
.list-date {
font-weight: 200;
font-style: italic;
font-size: 12px;
padding: 0 5px 0 5px;
}
.list-text {
padding: 0 5px 5px 5px;
border-bottom: solid 1px black;
}
notePad {
display: inline-block;
border: solid 3px black;
border-radius: 10px;
height: 400px;
overflow: scroll;
width: 60%;
margin-left: 5%;
margin-top: 0;
}
#note-title {
font-size: 24px;
padding: 0 0 5px 5px;
border-bottom: solid 2px #DEDEDE;
}
#note-body {
padding: 5px;
}
#body-field, #title-field {
width: 100%;
border: none;
outline: none;
resize: none;
}
#title-field {
font-size: 18px;
font-weight: 600;
}
#body-field {
font-size: 14px;
font-weight: 500;
height: 400px;
}
#color-select {
display: flex;
flex-flow: row-reverse nowrap;
padding: 5px 10px 0 0;
}
.color-box {
border: solid 2px #929292;
height: 10px;
width: 10px;
margin-left: 5px;
}
.display {
display: visible;
}
.no-display {
display: none;
}
button {
margin: 5px;
border: solid 3px grey;
border-radius: 10%;
font-size: 22px;
font-weight: 800;
text-transform: uppercase;
color: #DEDEDE;
}
button:hover, .color-box:hover {
cursor: pointer;
}
#listed:nth-child(odd):hover {
cursor: pointer;
}
#btn-save {
background-color: #2F5032;
}
#btn-delete {
background-color: #E41A36;
}
.white {
background-color: white;
}
.orange {
background-color: #FFD37F;
}
.banana {
background-color: #FFFA81;
}
.honeydew {
background-color: #D5FA80;
}
.flora {
background-color: #78F87F;
}
.aqua {
background-color: #79FBD6;
}
.ice {
background-color: #79FDFE;
}
.sky {
background-color: #7AD6FD;
}
.orchid {
background-color: #7B84FC;
}
.lavendar {
background-color: #D687FC;
}
.pink {
background-color: #FF89FD;
}
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title></title>
<link rel='stylesheet' href='style.css'>
</head>
<body>
<header>
The Note Machine
<div id='color-select'>
<div class='color-box white'></div>
<div class='color-box orange'></div>
<div class='color-box banana'></div>
<div class='color-box honeydew'></div>
<div class='color-box flora'></div>
<div class='color-box aqua'></div>
<div class='color-box ice'></div>
<div class='color-box sky'></div>
<div class='color-box orchid'></div>
<div class='color-box lavendar'></div>
<div class='color-box pink'></div>
</div>
</header>
<main>
<div class="headers">
<div id="list-head">
<b>Your Notes</b> <i>(click to edit/delete)</i>
</div>
<div id="note-head">
<b>Your Notepad</b>
<span id="edit-mode" class="no-display">
<i> (edit mode) </i>
</span>
</div>
</div>
<noteList>
<div id='listed'>
</div>
</noteList>
<notepad>
<div id="note-title">
<input id="title-field" type="text" placeholder="title your note">
</div>
<div id="note-body">
<textarea id="body-field"></textarea>
</div>
</notepad>
</main>
<footer>
<button id="btn-save">Save</button>
<button id="btn-delete">Delete / Clear </button>
</footer>
</body>
<script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js'></script>
<script type='text/javascript' src='app.js'></script>
</html>
I tried searching in the net for other notepads, but they aren't working on my blog, and here's the one that is finally working. I would really appreciate any kind of suggestions and assistance. T
If all you want to do is save to LocalStorage when save is clicked, then it would be as simple as saving the title and body variables to LocalStorage in the $('#btn-save').click() handler.
Assuming that (as #Nawed Khan guessed) you want to have the note saved without the user having to click save, then you'll want to make three changes:
In the main body of your $(document).ready() function, check for existing LocalStorage values, and if they exist, then set them on your $('#title-field') and $('#body-field') elements.
Add two new change handlers to your $('#title-field') and $('#body-field') elements. When these change handlers fire, get the title and body values from the elements and save them to LocalStorage.
In the $('#btn-save').click() and $('#btn-delete').click() handlers, reset the LocalStorage values of the active note.
You should find these links useful:
https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
https://api.jquery.com/change/
P.S. The information stored in LocalStorage can be lost if the user chooses to clear their browser data. If preservation of the data is vital, then implementing a solution using AJAX to connect to a database as #The Rahul Jha suggested would guarantee preservation of the data.
Yes , You can save the data in localStorage and fetch the data on page load. To set the localStorage item add below function in your script which is setting the item on keyup of textarea in localstorage.
$(document).on("keyup","#body-field",function(){
var text = $("#body-field").val();
localStorage.setItem("savedData", text);
});
Add below method to fetch the data from local storage
function loadDataFromLocalStorage(){
if (localStorage.getItem("savedData") !== null) {
$("#body-field").val(localStorage.getItem("savedData"))
}
}
And at last call the above method in $(document).ready() or page load to set the data back in text area after page load.
Put this inside the $(document).ready block:
$(“#title-field”).val(window.localStorage.getItem(“title”) || “”);
$(“#body-field”).val(window.localStorage.getItem(“body”) || “”);
$(“#title-field, #body-field”).change(function() {
var title = $(“#title-field”).val();
var body = $(“#body-field”).val();
window.localStorage.setItem(“title”, title);
window.localStorage.setItem(“body”, body)
})
The 2 first lines will load the text from the localStorage and sets the data on the corresponding inputs
The rest of the code is the part where the data is being saved to localStorage every time the value of #title-field OR #body-field changes.

Display text in input of type number only on focus

Here is what I try to acomplish: I need an input field containing a value with a unit, that would look like this:
On focussing the input, I want it to move the unit to the right side, looking like this:
I can think of two ways to do so:
1. Replace input field with a Div that looks exactly like the input when focus is lost, and set the value of the input as its content:
$('#fakeInput').bind('click', changeToRealInput);
$('#realInput').bind('blur', changeToFakeInput);
$('#realInput').trigger('blur');
$('#unitAddon').html($('#realInput').attr('unit'));
function changeToFakeInput() {
// hide actual input and show a div with its contents instead
$('#fakeInput').show();
$('#realInputContainer').hide();
$('#fakeInput').html($('#realInput').val() + $('#realInput').attr('unit'));
}
function changeToRealInput() {
// hide fake-div and set the actual input active
$('#fakeInput').hide();
$('#realInputContainer').show();
$('#realInput').focus();
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
div#container {
display: flex;
background: #8aaac7;
padding: 10px;
width: 200px;
}
div#unitAddon,
input#realInput,
div#fakeInput {
font-family: sans-serif;
font-size: 26px;
padding: 5px;
width: 100%;
background-color: #FFFFFF;
border: none;
outline: none;
}
div#realInputContainer,
div#fakeInput {
border: 2px solid #dadada;
}
div#realInputContainer {
display: flex;
}
div#unitAddon {
width: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="container">
<div id="fakeInput"></div>
<div id="realInputContainer">
<input type="number" unit="kg" id="realInput" value="3.3">
<div id="unitAddon"></div>
</div>
</div>
(also see this jsFiddle)
Problem here is (as you can see in the screenshot above) that, depending on your local settings, chrome automatically converts the decimal point into a comma (in the input, but not in the fake-div)
Another way I thought of is: When the focus is lost, set the size of the input field to match its content and, by doing so, pull the addon displaying the unit just behind the number.
Problem here is to get the size of the content of an input (cross-browser):
$('#realInput').bind('focus', changeToRealInput);
$('#realInput').bind('blur', changeToFakeInput);
$('#realInput').trigger('blur');
$('#unitAddon').html($('#realInput').attr('unit'));
function changeToFakeInput() {
// here is the question: what width should it be?
$('#realInput').css({'width' : '40%'});
}
function changeToRealInput() {
$('#unitAddon').css({'width' : 'auto'});
$('#realInput').css({'width' : '100%'});
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
div#container {
display: flex;
background: #8aaac7;
padding: 10px;
width: 300px;
}
div#unitAddon,
input#realInput{
font-family: sans-serif;
font-size: 26px;
padding: 5px;
width: 100%;
border: none;
outline: none;
}
div#realInputContainer {
border: 2px solid #dadada;
display: flex;
background-color: #FFFFFF;
}
div#realInputContainer.setAddonAway > div#unitAddon {
width: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="container">
<div id="realInputContainer" class="setAddonClose">
<input type="number" unit="kg" id="realInput" value="3.3">
<div id="unitAddon"></div>
</div>
</div>
also see this jsFiddle
I could accomlish this with an input[type=text], but I dont want to loose the benefits of type[number] (min/max/step validation, on-screen keyboard, etc.)
Is there any way of getting around the flaws of my two ideas? Or is thre a more elegant way to do so?
The idea is to: (1) make the input box to cover the entire container; (2) create a helper element, and set it the same length as the input value via JS, and make it invisible as a place holder; (3) apply some style for moving around the unit box.
codepen
$(document).ready(function() {
$(".value").text($(".number").val());
$(".unit").text($(".number").attr("unit"));
$(".number").on("change keypress input", function() {
$(".value").text($(".number").val());
});
});
* {
box-sizing: border-box;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.container {
position: relative;
display: flex;
border: 4px solid teal;
width: 200px;
}
.container > * {
font-family: sans-serif;
font-size: 20px;
}
.number {
position: absolute;
left: 0;
top: 0;
width: 100%;
padding: 0;
border: 0;
outline: 0;
background: transparent;
}
.value {
visibility: hidden;
max-width: 100%;
overflow: hidden;
}
.unit {
position: relative;
flex: 1;
pointer-events: none;
background: white;
}
.number:focus ~ .value {
flex: 1;
}
.number:focus ~ .unit {
flex: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<input class="number" type="number" value="1.23" unit="kg">
<span class="value"></span>
<span class="unit"></span>
</div>

Translating jQuery to Vanilla JS issue

I was watching a tutorial that used jQuery and wanted to turn it into JS, but my code is broken - was hoping someone could help me with this:
Tutorial JS:
$(function() {
var btn = $('button');
var progressBar = $('.progressbar');
btn.click(function() {
progressBar.find('li.active').next().addClass('active');
})
})
Taken from URL:http://www.kodhus.com/kodity/codify/kod/mGXAtb
Here is my failed attempt at rewriting the jQuery using JavaScript DOM:
var btn1 = document.getElementsByTagName('BUTTON');
var progBar = document.getElementsByClassName('progressbar');
function clickMe1() {
var elm = progBar.querySelectorAll("li");
var emlClass = elm.querySelector(".active");
return emlClass.nextElementSibling.addClass('active');
}
btn1.addEventListener("click", clickMe1, false);
where did I go wrong?
Working fiddle.
Your code will work after several changes check the notes below :
You've missed addClass() there it's a jQuery function, for vanilla JS use .classList.add() instead:
return emlClass.nextElementSibling.classList.add("active");
querySelectorAll(); will return a list of nodes you have to loop through them and add class, use :
var emlClass = progBar.querySelectorAll("li.active");
Instead of :
var elm = progBar.querySelectorAll("li");
var emlClass = elm.querySelector(".active");
Then loop and add active class:
for(var i=0;i<emlClass.length;i++){
emlClass[i].nextElementSibling.classList.add("active");
}
getElementsByTagName() and getElementsByClassName() will also returns a list of nodes with given name, you have to specify which one you want to pick (selecting the first in my example) :
var btn1 = document.getElementsByTagName('BUTTON')[0];
var progBar = document.getElementsByClassName('progressbar')[0];
Hope this helps.
var btn1 = document.getElementsByTagName('BUTTON')[0];
var progBar = document.getElementsByClassName('progressbar')[0];
function clickMe1() {
var emlClass = progBar.querySelectorAll("li.active");
for(var i=0;i<emlClass.length;i++){
emlClass[i].nextElementSibling.classList.add("active");
}
}
btn1.addEventListener("click", clickMe1, false);
.container {
width: 100%;
}
.progressbar {
counter-reset: step;
margin: 0;
margin-top: 50px;
padding: 0;
}
.progressbar li {
list-style-type: none;
float: left;
width: 33.33%;
position: relative;
text-align: center;
}
.progressbar li:before {
content: counter(step);
counter-increment: step;
width: 30px;
height: 30px;
line-height: 30px;
border: 2px solid #ddd;
display: block;
text-align: center;
margin: 0 auto 10px auto;
border-radius: 50%;
background-color: white;
}
.progressbar li:after {
content: '';
position: absolute;
width: 100%;
height: 2px;
background-color: #ddd;
top: 15px;
left: -50%;
z-index: -1;
}
.progressbar li:first-child:after {
content: none;
}
.progressbar li.active {
color: green;
}
.progressbar li.active:before {
border-color: green;
}
.progressbar li.active + li:after {
background-color: green;
}
button {
position: relative;
border: none;
padding: 10px 20px;
font-size: 16px;
border-radius: 2px;
left: 50%;
margin-top: 30px;
transform: translate(-50%);
cursor: pointer;
outline: none;
}
button:hover {
opacity: 0.8;
}
<div class="container">
<ul class="progressbar">
<li class="active">Step 1</li>
<li>Step 2</li>
<li>Step 3</li>
</ul>
</div>
<button>Next step</button>
.querySelectorAll("li") will return an array (or an array-like object) with one or more <li> tags. So you need to either:
loop through every <li> in that list and do the rest,
or just take the first item from that list if you don't want to worry about there being more than one li in the page,
or use .querySelector (not .querySelectorAll) to just take the first <li> for you.
MDN

Jquery: unable to add whitespace to the placeholder of contenteditable div

For my contetedible div, I need to use javascript to prepend some whitespace in the placeholder, in order to center the text of a flexible-length placeholder.
However, it seems impossbile to add multiple whitespace before the paceholder text.
Demo below:
<html>
box1
<div id="comment_box1" class="comment_box" contenteditable="true" data-placeholder=" somewords"></div>
box2
<div id="comment_box2" class="comment_box" contenteditable="true" data-placeholder=" "></div>
</html>
<style>
.comment_box[data-placeholder]:not(:focus):not([data-div-placeholder-content]):before {
content: attr(data-placeholder);
color: #aaa;
}
.comment_box{
min-height: 80px;
border: 1px solid orange;
width: 550px;
text-align: left;
}
</style>
<script>
$(document).ready(function(){
alert("I need to use jquery to make box2 same as box1");
var a=" ".repeat(3); // I tired var a=" &nbsp" not working also
var b="somewords";
$("#comment_box2").attr("data-placeholder",a+b);
});
</script>
you are dealing with non breaking spaces (5 of them), so you need to use the correct char:
<script>
$(document).ready(function(){
alert("I need to use jquery to make box2 same as box1");
var a= String.fromCharCode(160).repeat(5);
var b="somewords";
$("#comment_box2").attr("data-placeholder",a+b);
});
</script>
https://jsfiddle.net/mt5zy5r8/
Though if alignment is your goal, css is a far better solution, as noted by #Cbroe in comments:
.comment_box[data-placeholder]:not(:focus):not([data-div-placeholder-content]):before {
content: attr(data-placeholder);
color: #aaa;
display: block;
text-align: center;
}
https://jsfiddle.net/mt5zy5r8/1/
Here is an updated version of your script:
$(document).ready(function(){
alert("I need to use jquery to make box2 same as box1");
var a= $("#comment_box1").attr("data-placeholder"); // I tired var a=" &nbsp" not working also
var b="somewords";
$("#comment_box2").attr("data-placeholder",a);
});
It gets the attr value from comment_box1 stores it in a and places it in comment_box2
You should use css to align the text in the placeholder, use the pseudo classes for input-placeholder.
Here is an example of the snippet, i add some classes to style text inside the input, and also the input itself when it has a placeholder text:
.first-input {
width: 100px;
}
.second-input {
width: 300px;
}
.third-input {
width: 500px;
color: red;
}
input {
font-size: 15px;
padding: 10px;
margin: 10px;
}
input:placeholder-shown {
border-color: red;
}
::-webkit-input-placeholder {
text-align: center;
letter-spacing: 3px;
}
::-moz-placeholder {
text-align: center;
letter-spacing: 3px;
}
:-ms-input-placeholder {
text-align: center;
letter-spacing: 3px;
}
:-moz-placeholder {
text-align: center;
letter-spacing: 3px;
}
<input type="text" class="first-input" placeholder="hello">
<input type="text" class="second-input" placeholder="hello">
<input type="text" class="third-input" placeholder="">

CKEDITOR Drag and drop plugin integration stops working after editor instance is destroyed and recreated

I'm having quite a bit of trouble while trying to use CKEditor's drag and drop integration.
At first, dragging and dropping into the editor works allright with dataTransfer and all. But whenever I have to destroy and recreate an instance of the editor, dragging and dropping content stops working as expected.
I have modified the sample code directly from CKEditor's SDK page about DnD integration, where you can see the issue being reproduced.
(I just reduced the example as to make it more succint and added the "Destroy and recreate" button at the bottom of the list.)
Could not get it to work in JSFiddle, so sorry about that, but here's the code:
'use strict';
var CONTACTS = [{
name: 'Huckleberry Finn',
tel: '+48 1345 234 235',
email: 'h.finn#example.com',
avatar: 'hfin'
}, {
name: 'D\'Artagnan',
tel: '+45 2345 234 235',
email: 'dartagnan#example.com',
avatar: 'dartagnan'
}];
CKEDITOR.disableAutoInline = true;
CKEDITOR.plugins.add('drag_list', {
requires: 'widget',
init: function(editor) {
editor.widgets.add('drag_list', {
allowedContent: true,
pathName: 'drag_list',
upcast: function(el) {
return el.name == 'table' && el.hasClass('product_widget');
}
});
editor.addFeature(editor.widgets.registered.drag_list);
editor.on('paste', function(evt) {
var contact = evt.data.dataTransfer.getData('contact');
if (!contact) {
return;
}
evt.data.dataValue =
'<span class="h-card">' +
'' + contact.name + '' +
' ' +
'<span class="p-tel">' + contact.tel + '</span>' +
'</span>';
});
}
});
CKEDITOR.document.getById('contactList').on('dragstart', function(evt) {
var target = evt.data.getTarget().getAscendant('div', true);
CKEDITOR.plugins.clipboard.initDragDataTransfer(evt);
var dataTransfer = evt.data.dataTransfer;
dataTransfer.setData('contact', CONTACTS[target.data('contact')]);
dataTransfer.setData('text/html', target.getText());
if (dataTransfer.$.setDragImage) {
dataTransfer.$.setDragImage(target.findOne('img').$, 0, 0);
}
});
CKEDITOR.inline('editor1', {
extraPlugins: 'drag_list,sourcedialog,justify'
});
function destroy_recreate() {
for (var instance in CKEDITOR.instances) {
console.log(CKEDITOR.instances[instance])
CKEDITOR.instances[instance].destroy();
}
CKEDITOR.inline('editor1', {
extraPlugins: 'drag_list,sourcedialog,justify'
});
}
.columns {
background: #fff;
padding: 20px;
border: 1px solid #E7E7E7;
}
.columns:after {
content: "";
clear: both;
display: block;
}
.columns > .editor {
float: left;
width: 65%;
position: relative;
z-index: 1;
}
.columns > .contacts {
float: right;
width: 35%;
box-sizing: border-box;
padding: 0 0 0 20px;
}
#contactList {
list-style-type: none;
margin: 0 !important;
padding: 0;
}
#contactList li {
background: #FAFAFA;
margin-bottom: 1px;
height: 56px;
line-height: 56px;
cursor: pointer;
}
#contactList li:nth-child(2n) {
background: #F3F3F3;
}
#contactList li:hover {
background: #FFFDE3;
border-left: 5px solid #DCDAC1;
margin-left: -5px;
}
.contact {
padding: 0 10px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.contact .u-photo {
display: inline-block;
vertical-align: middle;
margin-right: 10px;
}
#editor1 .h-card {
background: #FFFDE3;
padding: 3px 6px;
border-bottom: 1px dashed #ccc;
}
#editor1 {
border: 1px solid #E7E7E7;
padding: 0 20px;
background: #fff;
position: relative;
}
#editor1 .h-card .p-tel {
font-style: italic;
}
#editor1 .h-card .p-tel::before,
#editor1 .h-card .p-tel::after {
font-style: normal;
}
#editor1 .h-card .p-tel::before {
content: "(☎ ";
}
#editor1 .h-card .p-tel::after {
content: ")";
}
#editor1 h1 {
text-align: center;
}
#editor1 hr {
border-style: dotted;
border-color: #DCDCDC;
border-width: 1px 0 0;
}
<script src="http://cdn.ckeditor.com/4.5.5/standard-all/ckeditor.js"></script>
<div class="columns">
<div class="editor">
<div cols="10" id="editor1" name="editor1" rows="10" contenteditable="true">
<h3>Drop stuff here then press the Destroy/Recreate button and try again.</h3>
</div>
</div>
<div class="contacts">
<h3>List of Droppable Contacts</h3>
<ul id="contactList">
<li>
<div class="contact h-card" data-contact="0" draggable="true" tabindex="0">
<img src="http://sdk.ckeditor.com/samples/assets/draganddrop/img/hfin.png" alt="avatar" class="u-photo">Huckleberry Finn
</div>
</li>
<li>
<div class="contact h-card" data-contact="1" draggable="true" tabindex="0">
<img src="http://sdk.ckeditor.com/samples/assets/draganddrop/img/dartagnan.png" alt="avatar" class="u-photo">D'Artagnan
</div>
</li>
</ul>
<button class='destroy_recreate' onclick='destroy_recreate()'>Destroy and recreate editors</button>
</div>
</div>
Other plugins like sourcedialog and justify seem to keep working well, but drag_list does not.
Does anyone know why this is happening? What do I have to do to be able to drag and drop content such as the example's hcards in a newly created CKEditor instance?
Thanks in advance.
It looks like a nasty bug in the editor core. I checked it and reported a ticket: https://dev.ckeditor.com/ticket/14339 Until the ticket will be fixed, all I can suggest is to reattach dragstart event on the editor recreation. You can put: CKEDITOR.document.getById('contactList').on('dragstart', ... ); inside the plugin init method. After such change drag and drop should work, but dragstart will be fired multiple times. You can detach the dragstart event, before you attach it again end everything should work fine.

Categories