This commit is contained in:
khaydarov 2016-07-02 18:37:10 +03:00
commit 2f2f508659
6 changed files with 231 additions and 52 deletions

View file

@ -722,6 +722,13 @@ cEditor.callback = {
return false; return false;
} }
/**
* LEFT or UP not at the beginning
*/
if ( selection.anchorOffset !== 0) {
return false;
}
/** Saving caret after keydown event happend */ /** Saving caret after keydown event happend */
cEditor.caret.save(); cEditor.caret.save();
@ -732,37 +739,43 @@ cEditor.callback = {
} }
/** /**
* Find deepest child node * Do nothing if caret is not at the beginning of first child
* Iterate child nodes and find First DEEPEST node
* We need it to check caret positon (it must be at the begining)
*/ */
focusedNodeHolder = focusedNodeHolder || focusedNode; var caretInFirstChild = false,
caretAtTheBeginning = false;
if (focusedNodeHolder.childNodes.length !== 0) { var editableElement = focusedNode.querySelector('[contenteditable]'),
firstChild,
deepestTextnode;
var focusedTextNode = ''; if (!editableElement) {
cEditor.core.log('Can not find editable element in current block: %o', 'warn', focusedNode);
if (focusedNodeHolder.childNodes){
/** Looking from the first child */
focusedTextNode = cEditor.content.getDeepestTextNodeFromPosition(focusedNodeHolder, 0);
}
}
/**
* When we click "UP" or "LEFT", caret behaviour is as default.
* We should check caret position before we transmit/switch the block.
*/
if ( selection.anchorOffset !== 0) {
return false;
}
/**
* We can't switch block till caret is not at the begining of first node and has zero offset
*/
if ( (cEditor.caret.offset !== 0 || cEditor.caret.focusedNodeIndex !== 0) && focusedNodeHolder.childNodes.length !== 0 ) {
return; return;
} }
cEditor.caret.setToPreviousBlock(block); firstChild = editableElement.childNodes[0];
if (cEditor.core.isDomNode(firstChild)) {
deepestTextnode = cEditor.content.getDeepestTextNodeFromPosition(firstChild, 0);
} else {
deepestTextnode = firstChild;
}
caretInFirstChild = selection.anchorNode == deepestTextnode;
caretAtTheBeginning = cEditor.caret.offset === 0;
console.log("каретка в первом узле: %o", caretInFirstChild);
console.log("каретка в начале первого узла: %o", caretAtTheBeginning);
if ( caretInFirstChild && caretAtTheBeginning ) {
cEditor.caret.setToPreviousBlock(focusedNode);
}
}, },
@ -1288,7 +1301,7 @@ cEditor.caret = {
console.log("nextBlock: %o", nextBlock); console.log("nextBlock: %o", nextBlock);
nextBlockEditableElement = nextBlock.querySelector('[contenteditable], [contenteditable="true"]'); nextBlockEditableElement = nextBlock.querySelector('[contenteditable]');
console.log("nextBlockEditableElement: %o", nextBlockEditableElement); console.log("nextBlockEditableElement: %o", nextBlockEditableElement);
@ -1302,6 +1315,9 @@ cEditor.caret = {
cEditor.content.workingNodeChanged(block.nextSibling); cEditor.content.workingNodeChanged(block.nextSibling);
}, },
/**
* @todo передалать на prevBlock.querySelector('[contenteditable]') по аналогии с setToNextBlock
*/
setToPreviousBlock : function(block) { setToPreviousBlock : function(block) {
if ( !block.previousSibling ) { if ( !block.previousSibling ) {

View file

@ -20,9 +20,11 @@
font-size: 2em; font-size: 2em;
} }
</style> </style>
<link rel="stylesheet" href="plugins/ceditor-tool-link.css" />
<link rel="stylesheet" href="plugins/ceditor-tool-link/ceditor-tool-link.css" />
<link rel="stylesheet" href="plugins/ceditor-tool-quote/ceditor-tool-quote.css" /> <link rel="stylesheet" href="plugins/ceditor-tool-quote/ceditor-tool-quote.css" />
<link rel="stylesheet" href="plugins/images/plugin.css" /> <link rel="stylesheet" href="plugins/images/plugin.css" />
</head> </head>
<body style="padding: 100px"> <body style="padding: 100px">
@ -168,7 +170,7 @@
link : { link : {
'linkUrl' : 'http://google.com', 'linkUrl' : 'http://google.com',
'linkText' : 'google.com', 'linkText' : 'google.com',
'image' : 'http://i1.kym-cdn.com/photos/images/facebook/000/002/110/longcat.jpg', 'image' : 'http://2.bp.blogspot.com/-7bZ5EziliZQ/VynIS9F7OAI/AAAAAAAASQ0/BJFntXCAntstZe6hQuo5KTrhi5Dyz9yHgCK4B/s1600/googlelogo_color_200x200.png',
'title' : 'Google', 'title' : 'Google',
'description' : 'Поисковик, поисковик, проч.' 'description' : 'Поисковик, поисковик, проч.'
} }
@ -268,6 +270,6 @@
</script> </script>
<script src="plugins/ceditor-tool-link.js"></script> <script src="plugins/ceditor-tool-link/ceditor-tool-link.js"></script>
<script src="plugins/ceditor-tool-quote/ceditor-tool-quote.js"></script> <script src="plugins/ceditor-tool-quote/ceditor-tool-quote.js"></script>
<script src="plugins/images/plugin.js"></script> <script src="plugins/images/plugin.js"></script>

View file

@ -11,6 +11,10 @@
outline: none; outline: none;
border: 0; border: 0;
width: 100%; width: 100%;
background: transparent;
font-size: 1em;
padding: 12px;
transition: background 200ms;
} }
.tool-link-panel { .tool-link-panel {
@ -57,3 +61,23 @@
text-decoration: none; text-decoration: none;
color: rgba(165,156,86,.8); color: rgba(165,156,86,.8);
} }
.tool-link-loader {
background: url("loading.gif") !important;
opacity: 0.1;
}
.tool-link-error {
/*background: repeating-linear-gradient(*/
/*45deg,*/
/*#bc320e,*/
/*#606dbc 10px,*/
/*#465298 10px,*/
/*#465298 20px*/
/*);*/
background: rgba(255, 0, 0, 0.9);
}

View file

@ -8,13 +8,17 @@
var linkTool = { var linkTool = {
defaultText : 'Insert link here ...', defaultText : 'Insert link here ...',
ENTER_KEY : 13,
currentBlock : null, currentBlock : null,
currentInput : null, currentInput : null,
elementClasses : { elementClasses : {
link : "tool-link-link", link : "tool-link-link",
image : "tool-link-image", image : "tool-link-image",
title : "tool-link-title", title : "tool-link-title",
description : "tool-link-description" description : "tool-link-description",
loader : "tool-link-loader",
error : "tool-link-error"
}, },
/** /**
@ -36,6 +40,8 @@ var linkTool = {
tag.addEventListener('paste', linkTool.blockPasteCallback, false); tag.addEventListener('paste', linkTool.blockPasteCallback, false);
tag.addEventListener('keydown', linkTool.blockKeyDownCallback, false);
return wrapper; return wrapper;
}, },
@ -82,19 +88,53 @@ var linkTool = {
blockPasteCallback : function (event) { blockPasteCallback : function (event) {
clipboardData = event.clipboardData || window.clipboardData; var clipboardData = event.clipboardData || window.clipboardData,
pastedData = clipboardData.getData('Text'),
block = event.target.parentNode;
pastedData = clipboardData.getData('Text'); linkTool.renderLink(pastedData, block);
var block = event.target.parentNode; event.stopPropagation();
},
blockKeyDownCallback : function (event) {
var inputTag = event.target,
block = inputTag.parentNode;
if (block.classList.contains(linkTool.elementClasses.error))
{
block.classList.remove(linkTool.elementClasses.error)
}
if (event.keyCode == linkTool.ENTER_KEY) {
var url = inputTag.value;
linkTool.renderLink(url, block);
event.preventDefault();
}
},
renderLink : function (url, block) {
Promise.resolve() Promise.resolve()
.then(function () { .then(function () {
return linkTool.urlify(pastedData) return linkTool.urlify(url)
}) })
.then(fetch('http://ajax.ru/link')) .then(function (url) {
/* Show loader gif **/
block.classList.add(linkTool.elementClasses.loader);
return fetch('/server/?url=' + encodeURI(url));
})
.then(function (response) { .then(function (response) {
@ -105,13 +145,7 @@ var linkTool = {
} }
else { else {
return { return Error("Invalid response status: %o", response);
'linkUrl' : 'http://yandex.ru',
'linkText' : 'yandex.ru',
'image' : 'https://yastatic.net/morda-logo/i/apple-touch-icon/ru-76x76.png',
'title' : 'Яндекс',
'description' : 'Сайт, поисковик, проч.'
};
} }
@ -122,6 +156,12 @@ var linkTool = {
}) })
.catch(function(error) { .catch(function(error) {
/* Hide loader gif **/
block.classList.remove(linkTool.elementClasses.loader);
block.classList.add(linkTool.elementClasses.error);
cEditor.core.log('Error while doing things with link paste: %o', 'error', error); cEditor.core.log('Error while doing things with link paste: %o', 'error', error);
}); });
@ -137,7 +177,7 @@ var linkTool = {
return links[0]; return links[0];
} }
return null; return Promise.reject(Error("Url is not matched"));
}, },
@ -155,6 +195,8 @@ var linkTool = {
currentBlock.appendChild(previewBlock); currentBlock.appendChild(previewBlock);
currentBlock.classList.remove(linkTool.elementClasses.loader);
} }
}; };
@ -164,7 +206,7 @@ linkTool.ui = {
make : function (json) { make : function (json) {
var wrapper = this.wrapper(), var wrapper = this.wrapper(),
siteImage = this.image(json.image), siteImage = this.image(json.image, linkTool.elementClasses.image),
siteTitle = this.title(json.title), siteTitle = this.title(json.title),
siteDescription = this.description(json.description), siteDescription = this.description(json.description),
siteLink = this.link(json.linkUrl, json.linkText); siteLink = this.link(json.linkUrl, json.linkText);
@ -190,15 +232,15 @@ linkTool.ui = {
input : function () { input : function () {
var inpitTag = document.createElement('input'); var inputTag = document.createElement('input');
inpitTag.classList += "ceditor-tool-link-input"; inputTag.classList += "ceditor-tool-link-input";
inpitTag.placeholder = linkTool.defaultText; inputTag.placeholder = linkTool.defaultText;
inpitTag.contentEditable = false; inputTag.contentEditable = false;
return inpitTag; return inputTag;
}, },
@ -212,11 +254,11 @@ linkTool.ui = {
}, },
image : function (imageSrc) { image : function (imageSrc, imageClass) {
var imageTag = document.createElement('img'); var imageTag = document.createElement('img');
imageTag.classList += linkTool.elementClasses.image; imageTag.classList += imageClass;
imageTag.setAttribute('src', imageSrc); imageTag.setAttribute('src', imageSrc);
@ -260,7 +302,7 @@ linkTool.ui = {
descriptionTag.innerHTML = descriptionText; descriptionTag.innerHTML = descriptionText;
return descriptionTag; return descriptionTag;
} },
}; };

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

95
server/index.php Normal file
View file

@ -0,0 +1,95 @@
<?php
function file_get_contents_curl($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 8);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch,CURLOPT_USERAGENT,'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36');
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
function get_url()
{
if (!isset($_GET['url']))
{
return false;
}
$url = $_GET['url'];
if (filter_var($url, FILTER_VALIDATE_URL) === FALSE) {
return false;
}
return $url;
}
function get_meta_from_html($html)
{
$doc = new DOMDocument();
@$doc->loadHTML($html);
$nodes = $doc->getElementsByTagName('title');
$title = $nodes->item(0)->nodeValue;
$description = "";
$keywords = "";
$image = "";
$metas = $doc->getElementsByTagName('meta');
for ($i = 0; $i < $metas->length; $i++)
{
$meta = $metas->item($i);
if($meta->getAttribute('name') == 'description')
$description = $meta->getAttribute('content');
if($meta->getAttribute('name') == 'keywords')
$keywords = $meta->getAttribute('content');
if($meta->getAttribute('property')=='og:image'){
$image = $meta->getAttribute('content');
}
}
return [
'image' => $image,
'title' => $title,
'description' => $description
];
}
$url = get_url();
$url_params = parse_url($url);
if (!$url)
{
exit(0);
}
$html = file_get_contents_curl($url);
$result = get_meta_from_html($html);
$result = array_merge(
get_meta_from_html($html),
array(
'linkUrl' => $url,
'linkText' => $url_params["host"] . $url_params["path"],
)
);
echo json_encode($result);
?>