diff --git a/codex-editor.js b/codex-editor.js index 14f66764..17f08002 100644 --- a/codex-editor.js +++ b/codex-editor.js @@ -722,6 +722,13 @@ cEditor.callback = { return false; } + /** + * LEFT or UP not at the beginning + */ + if ( selection.anchorOffset !== 0) { + return false; + } + /** Saving caret after keydown event happend */ cEditor.caret.save(); @@ -732,37 +739,43 @@ cEditor.callback = { } /** - * Find deepest child node - * Iterate child nodes and find First DEEPEST node - * We need it to check caret positon (it must be at the begining) + * Do nothing if caret is not at the beginning of first child */ - focusedNodeHolder = focusedNodeHolder || focusedNode; + var caretInFirstChild = false, + caretAtTheBeginning = false; - if (focusedNodeHolder.childNodes.length !== 0) { + var editableElement = focusedNode.querySelector('[contenteditable]'), + firstChild, + deepestTextnode; - var focusedTextNode = ''; - - 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 ) { + if (!editableElement) { + cEditor.core.log('Can not find editable element in current block: %o', 'warn', focusedNode); 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); - nextBlockEditableElement = nextBlock.querySelector('[contenteditable], [contenteditable="true"]'); + nextBlockEditableElement = nextBlock.querySelector('[contenteditable]'); console.log("nextBlockEditableElement: %o", nextBlockEditableElement); @@ -1302,6 +1315,9 @@ cEditor.caret = { cEditor.content.workingNodeChanged(block.nextSibling); }, + /** + * @todo передалать на prevBlock.querySelector('[contenteditable]') по аналогии с setToNextBlock + */ setToPreviousBlock : function(block) { if ( !block.previousSibling ) { diff --git a/example.html b/example.html index e5ffda73..db10e6e2 100644 --- a/example.html +++ b/example.html @@ -20,9 +20,11 @@ font-size: 2em; } - + + + @@ -168,7 +170,7 @@ link : { 'linkUrl' : 'http://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', 'description' : 'Поисковик, поисковик, проч.' } @@ -268,6 +270,6 @@ - + diff --git a/plugins/ceditor-tool-link.css b/plugins/ceditor-tool-link/ceditor-tool-link.css similarity index 70% rename from plugins/ceditor-tool-link.css rename to plugins/ceditor-tool-link/ceditor-tool-link.css index 330dc089..6ef9e80f 100644 --- a/plugins/ceditor-tool-link.css +++ b/plugins/ceditor-tool-link/ceditor-tool-link.css @@ -11,6 +11,10 @@ outline: none; border: 0; width: 100%; + background: transparent; + font-size: 1em; + padding: 12px; + transition: background 200ms; } .tool-link-panel { @@ -57,3 +61,23 @@ text-decoration: none; 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); + +} \ No newline at end of file diff --git a/plugins/ceditor-tool-link.js b/plugins/ceditor-tool-link/ceditor-tool-link.js similarity index 70% rename from plugins/ceditor-tool-link.js rename to plugins/ceditor-tool-link/ceditor-tool-link.js index c4c26b12..568fb829 100644 --- a/plugins/ceditor-tool-link.js +++ b/plugins/ceditor-tool-link/ceditor-tool-link.js @@ -8,13 +8,17 @@ var linkTool = { defaultText : 'Insert link here ...', + ENTER_KEY : 13, + currentBlock : null, currentInput : null, elementClasses : { link : "tool-link-link", image : "tool-link-image", 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('keydown', linkTool.blockKeyDownCallback, false); + return wrapper; }, @@ -82,19 +88,53 @@ var linkTool = { 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() .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) { @@ -105,13 +145,7 @@ var linkTool = { } else { - return { - 'linkUrl' : 'http://yandex.ru', - 'linkText' : 'yandex.ru', - 'image' : 'https://yastatic.net/morda-logo/i/apple-touch-icon/ru-76x76.png', - 'title' : 'Яндекс', - 'description' : 'Сайт, поисковик, проч.' - }; + return Error("Invalid response status: %o", response); } @@ -122,6 +156,12 @@ var linkTool = { }) .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); }); @@ -137,7 +177,7 @@ var linkTool = { return links[0]; } - return null; + return Promise.reject(Error("Url is not matched")); }, @@ -155,6 +195,8 @@ var linkTool = { currentBlock.appendChild(previewBlock); + currentBlock.classList.remove(linkTool.elementClasses.loader); + } }; @@ -164,7 +206,7 @@ linkTool.ui = { make : function (json) { var wrapper = this.wrapper(), - siteImage = this.image(json.image), + siteImage = this.image(json.image, linkTool.elementClasses.image), siteTitle = this.title(json.title), siteDescription = this.description(json.description), siteLink = this.link(json.linkUrl, json.linkText); @@ -190,15 +232,15 @@ linkTool.ui = { 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'); - imageTag.classList += linkTool.elementClasses.image; + imageTag.classList += imageClass; imageTag.setAttribute('src', imageSrc); @@ -260,7 +302,7 @@ linkTool.ui = { descriptionTag.innerHTML = descriptionText; return descriptionTag; - } + }, }; diff --git a/plugins/ceditor-tool-link/loading.gif b/plugins/ceditor-tool-link/loading.gif new file mode 100644 index 00000000..72ea7ccb Binary files /dev/null and b/plugins/ceditor-tool-link/loading.gif differ diff --git a/server/index.php b/server/index.php new file mode 100644 index 00000000..c70ec8a5 --- /dev/null +++ b/server/index.php @@ -0,0 +1,95 @@ +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); + +?> \ No newline at end of file