--- /dev/null
+/**\r
+ * Copyright (c) 2014 Leonardo Cardoso (http://leocardz.com)\r
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)\r
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.\r
+ * \r
+ * restructured from rabzuarus (https://friendica.kommune4.de/profile/rabuzarus)\r
+ * for the decental social network Friendica.\r
+ * \r
+ * Version: 1.4.0\r
+ */\r
+(function ($) {\r
+ $.fn.linkPreview = function (options) {\r
+ var opts = jQuery.extend({}, $.fn.linkPreview.defaults, options);\r
+\r
+ var selector = $(this).selector;\r
+ selector = selector.substr(1);\r
+\r
+ var previewTpl = '\\r
+ <div id="preview_' + selector + '" class="preview {0}">{1}</div>\\r
+ <div style="clear: both"></div>';\r
+ var attachmentTpl = '\\r
+ <hr class="previewseparator">\\r
+ <div id="closePreview_' + selector + '" title="Remove" class="closePreview" >\\r
+ <button type="button" class="previewActionBtn">×</button>\\r
+ </div>\\r
+ <div id="previewImages_' + selector + '" class="previewImages">\\r
+ <div id="previewImgBtn_' + selector + '" class="previewImgBtn">\\r
+ <button type="button" id="previewChangeImg_' + selector + '" class="buttonChangeDeactive previewActionBtn" style="display: none">\\r
+ <i class="fa fa-exchange" aria-hidden="true"></i>\\r
+ </button>\\r
+ </div>\\r
+ <div id="previewImage_' + selector + '" class="previewImage">\\r
+ </div>\\r
+ <input type="hidden" id="photoNumber_' + selector + '" class="photoNumber" value="0" />\\r
+ </div>\\r
+ <div id="previewContent_' + selector + '" class="previewContent">\\r
+ <h4 id="previewTitle_' + selector + '" class="previewTitle"></h4>\\r
+ <blockquote id="previewDescription_' + selector + '" class="previewDescription"></blockquote>\\r
+ <div id="hiddenDescription_' + selector + '" class="hiddenDescription"></div>\\r
+ <sup id="previewUrl_' + selector + '" class="previewUrl"></sup>\\r
+ </div>\\r
+ <div class="clear"></div>\\r
+ <hr class="previewseparator">';\r
+ var text;\r
+ var urlRegex = /(https?\:\/\/|\s)[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})(\/+[a-z0-9_.\:\;-]*)*(\?[\&\%\|\+a-z0-9_=,\.\:\;-]*)?([\&\%\|\+&a-z0-9_=,\:\;\.-]*)([\!\#\/\&\%\|\+a-z0-9_=,\:\;\.-]*)}*/i;\r
+ var binurl;\r
+ var block = false;\r
+ var blockTitle = false;\r
+ var blockDescription = false;\r
+ var cache = {};\r
+ var images = "";\r
+ var isExtern = false;\r
+ var photoNumber = 0;\r
+ var firstPosted = false;\r
+ var isActive = false;\r
+ var isCrawling = false;\r
+ var defaultTitle = opts.defaultTitle;\r
+ var defaultDescription = opts.defaultDescription;\r
+\r
+ var init = function() {\r
+ $('#' + selector).bind({\r
+ paste: function () {\r
+ setTimeout(function () {\r
+ crawlText();\r
+ }, 100);\r
+ },\r
+ keyup: function (e) {\r
+ // on enter, space, ctrl\r
+ if ((e.which === 13 || e.which === 32 || e.which === 17)) {\r
+ crawlText();\r
+ }\r
+ }\r
+ });\r
+ };\r
+ var resetPreview = function() {\r
+ $('#previewChangeImg_' + selector).removeClass('buttonChangeActive');\r
+ $('#previewChangeImg_' + selector).addClass('buttonChangeDeactive');\r
+ photoNumber = 0;\r
+ images = "";\r
+ }\r
+\r
+ var crawlText = function (text) {\r
+ block = false;\r
+ images = '';\r
+ isExtern = false;\r
+\r
+ if (typeof text === 'undefined') {\r
+ text = getPrevWord(selector);\r
+ } else {\r
+ isExtern = true;\r
+ }\r
+\r
+ if (trim(text) !== "") {\r
+ if (block === false && urlRegex.test(text)) {\r
+ binurl = bin2hex(text);\r
+ block = true;\r
+\r
+ isCrawling = true;\r
+ $('#profile-rotator').show();\r
+\r
+ if (binurl in cache) {\r
+ isCrawling = false;\r
+ processContentData(cache[binurl]);\r
+ } else {\r
+ getContentData(binurl, processContentData);\r
+ }\r
+ }\r
+ }\r
+ };\r
+\r
+ var processContentData = function(result) {\r
+ if (result.contentType === 'image') {\r
+ insertImage(result.data);\r
+ }\r
+ if (result.contentType === 'attachment') {\r
+ insertAttachment(result.data);\r
+ }\r
+ $('#profile-rotator').hide();\r
+ }\r
+\r
+ var getContentData = function(binurl, callback) {\r
+ $.get('parse_url?binurl='+ binurl + '&dataType=json', function (answer) {\r
+ if (typeof answer.contentType === 'undefined'\r
+ || answer.contentType === null)\r
+ {\r
+ answer.contentType = "";\r
+ }\r
+ if (typeof answer.data.url === 'undefined'\r
+ || answer.data.url === null)\r
+ {\r
+ answer.data.url = "";\r
+ }\r
+ if (typeof answer.data.title === 'undefined'\r
+ || answer.data.title === null\r
+ || answer.data.title === "")\r
+ {\r
+ answer.data.title = defaultTitle;\r
+ }\r
+ if (typeof answer.data.text === 'undefined'\r
+ || answer.data.text === null\r
+ || answer.data.text === "")\r
+ {\r
+ answer.data.text = "";\r
+ }\r
+ if (typeof answer.data.images === 'undefined'\r
+ || answer.data.images === null)\r
+ {\r
+ answer.data.images = "";\r
+ }\r
+\r
+ // Put the data into a cache\r
+ cache[binurl] = answer;\r
+\r
+ callback(answer);\r
+\r
+ isCrawling = false;\r
+ });\r
+ }\r
+\r
+ var insertImage = function(json) {\r
+ if (!isExtern) {\r
+ return\r
+ }\r
+ var bbcode = '\n[img]' + json.url + '[/img]\n';\r
+ addeditortext(bbcode);\r
+ };\r
+\r
+ var insertAudio = function(json) {\r
+ if (!isExtern) {\r
+ return\r
+ }\r
+ var bbcode = '\n[audio]' + json.url + '[/audio]\n';\r
+ addeditortext(bbcode);\r
+ };\r
+\r
+ var insertVideo = function(json) {\r
+ if (!isExtern) {\r
+ return\r
+ }\r
+ var bbcode = '\n[video]' + json.url + '[/video]\n';\r
+ addeditortext(bbcode);\r
+ };\r
+\r
+ var insertAttachment = function(json) {\r
+ // If we have already a preview, leaver here.\r
+ // Note: if we finish the Preview of other media content type,\r
+ // we can move this condition to the beggining of crawlText();\r
+ if (isActive) {\r
+ return;\r
+ }\r
+\r
+ if (json.type != 'link' && json.type != 'video' && json.type != 'photo' || json.url == json.title) {\r
+ return;\r
+ }\r
+\r
+ $('#photoNumber_' + selector).val(0);\r
+ resetPreview();\r
+\r
+ var typeClass = 'type-' + json.type;\r
+ var imageClass = 'attachment-preview';\r
+ var urlHost = "";\r
+ var description = json.text;\r
+\r
+ // Load and add the template if it isn't allready loaded.\r
+ if ($('#preview_' + selector).length == 0) {\r
+ var tpl = previewTpl.format(typeClass, attachmentTpl);\r
+ $('#' + selector).after(tpl);\r
+ }\r
+\r
+ isActive = true;\r
+\r
+ if (description === '') {\r
+ description = defaultDescription;\r
+ }\r
+\r
+ $('#previewTitle_' + selector).html("\\r
+ <span id='previewSpanTitle_" + selector + "' class='previewSpanTitle' >" + escapeHTML(json.title) + "</span>\\r
+ <input type='text' value='" + escapeHTML(json.title) + "' id='previewInputTitle_" + selector + "' class='previewInputTitle inputPreview' style='display: none;'/>"\r
+ );\r
+\r
+\r
+ $('#previewDescription_' + selector).html("\\r
+ <span id='previewSpanDescription_" + selector + "' class='previewSpanDescription' >" + escapeHTML(description) + "</span>\n\\r
+ <textarea id='previewInputDescription_" + selector + "' class='previewInputDescription' style='display: none;' class='inputPreview' >" + escapeHTML(json.text) + "</textarea>"\r
+ );\r
+\r
+ if (json.url) {\r
+ var regexpr = "(https?://)([^:^/]*)(:\\d*)?(.*)?";\r
+ var regResult = json.url.match(regexpr);\r
+ var urlHost = regResult[1] + regResult[2];\r
+ $('#previewUrl_' + selector).html("<a href='" + json.url + "'>" + urlHost + "</a>");\r
+ }\r
+\r
+ images = json.images;\r
+\r
+ if (Array.isArray(images)) {\r
+ $('#previewImages_' + selector).show();\r
+ } else {\r
+ $('#previewImages_' + selector).hide();\r
+ }\r
+\r
+ images.length = parseInt(images.length);\r
+ var appendImage = "";\r
+\r
+ for (i = 0; i < images.length; i++) {\r
+ // For small preview images we use a smaller attachment format.\r
+// if (Array.isArray(images) && typeof images[i].width !== 'undefined') {\r
+ ///@todo here we need to add a check for !Config::get('system', 'always_show_preview').\r
+ if (images[i].width >= 500 && images[i].width >= images[i].height) {\r
+ imageClass = 'attachment-image';\r
+ }\r
+// }\r
+ if (i === 0) {\r
+ appendImage += "<img id='imagePreview_" + selector + "_" + i + "' src='" + images[i].src + "' class='" + imageClass + "' ></img>";\r
+ } else {\r
+ appendImage += "<img id='imagePreview_" + selector + "_" + i + "' src='" + images[i].src + "' class='" + imageClass + "' style='display: none;'></img>";\r
+ }\r
+ }\r
+\r
+ $('#previewImage_' + selector).html(appendImage + "<div id='whiteImage' style='color: transparent; display:none;'>...</div>");\r
+\r
+ // more than just one image.\r
+ if (images.length > 1) {\r
+ // Enable the the button to change the preview pictures.\r
+ $('#previewChangeImg_' + selector).show();\r
+\r
+ if (firstPosted === false) {\r
+ firstPosted = true;\r
+\r
+ $('#previewChangeImg_' + selector).unbind('click').click(function (e) {\r
+ e.stopPropagation();\r
+ if (images.length > 1) {\r
+// photoNumber = parseInt($('#photoNumber_' + selector).val());\r
+ $('#imagePreview_' + selector + '_' + photoNumber).css({\r
+ 'display': 'none'\r
+ });\r
+ photoNumber += 1;\r
+\r
+ // If have reached the last image, begin with the first image.\r
+ if (photoNumber === images.length) {\r
+ photoNumber = 0;\r
+ }\r
+\r
+ $('#imagePreview_' + selector + '_' + photoNumber).css({\r
+ 'display': 'block'\r
+ });\r
+ $('#photoNumber_' + selector).val(photoNumber);\r
+ }\r
+ });\r
+ }\r
+ }\r
+\r
+ processEventListener();\r
+ $('#profile-rotator').hide();\r
+ };\r
+\r
+ var processEventListener = function() {\r
+ $('#previewSpanTitle_' + selector).unbind('click').click(function (e) {\r
+ e.stopPropagation();\r
+ if (blockTitle === false) {\r
+ blockTitle = true;\r
+ $('#previewSpanTitle_' + selector).hide();\r
+ $('#previewInputTitle_' + selector).show();\r
+ $('#previewInputTitle_' + selector).val($('#previewInputTitle_' + selector).val());\r
+ $('#previewInputTitle_' + selector).focus().select();\r
+ }\r
+ });\r
+\r
+ $('#previewInputTitle_' + selector).blur(function () {\r
+ blockTitle = false;\r
+ $('#previewSpanTitle_' + selector).html($('#previewInputTitle_' + selector).val());\r
+ $('#previewSpanTitle_' + selector).show();\r
+ $('#previewInputTitle_' + selector).hide();\r
+ });\r
+\r
+ $('#previewInputTitle_' + selector).keypress(function (e) {\r
+ if (e.which === 13) {\r
+ blockTitle = false;\r
+ $('#previewSpanTitle_' + selector).html($('#previewInputTitle_' + selector).val());\r
+ $('#previewSpanTitle_' + selector).show();\r
+ $('#previewInputTitle_' + selector).hide();\r
+ }\r
+ });\r
+\r
+ $('#previewSpanDescription_' + selector).unbind('click').click(function (e) {\r
+ e.stopPropagation();\r
+ if (blockDescription === false) {\r
+ blockDescription = true;\r
+ $('#previewSpanDescription_' + selector).hide();\r
+ $('#previewInputDescription_' + selector).show();\r
+ $('#previewInputDescription_' + selector).val($('#previewInputDescription_' + selector).val());\r
+ $('#previewInputDescription_' + selector).focus().select();\r
+ }\r
+ });\r
+\r
+ $('#previewInputDescription_' + selector).blur(function () {\r
+ blockDescription = false;\r
+ $('#previewSpanDescription_' + selector).html($('#previewInputDescription_' + selector).val());\r
+ $('#previewSpanDescription_' + selector).show();\r
+ $('#previewInputDescription_' + selector).hide();\r
+ });\r
+\r
+ $('#previewInputDescription_' + selector).keypress(function (e) {\r
+ if (e.which === 13) {\r
+ blockDescription = false;\r
+ $('#previewSpanDescription_' + selector).html($('#previewInputDescription_' + selector).val());\r
+ $('#previewSpanDescription_' + selector).show();\r
+ $('#previewInputDescription_' + selector).hide();\r
+ }\r
+ });\r
+\r
+ $('#previewSpanTitle_' + selector).mouseover(function () {\r
+ $('#previewSpanTitle_' + selector).css({\r
+ "background-color": "#ff9"\r
+ });\r
+ });\r
+\r
+ $('#previewSpanTitle_' + selector).mouseout(function () {\r
+ $('#previewSpanTitle_' + selector).css({\r
+ "background-color": "transparent"\r
+ });\r
+ });\r
+\r
+ $('#previewSpanDescription_' + selector).mouseover(function () {\r
+ $('#previewSpanDescription_' + selector).css({\r
+ "background-color": "#ff9"\r
+ });\r
+ });\r
+\r
+ $('#previewSpanDescription_' + selector).mouseout(function () {\r
+ $('#previewSpanDescription_' + selector).css({\r
+ "background-color": "transparent"\r
+ });\r
+ });\r
+\r
+ $('#closePreview_' + selector).unbind('click').click(function (e) {\r
+ e.stopPropagation();\r
+ block = false;\r
+ images = '';\r
+ isActive = false;\r
+ firstPosted = false;\r
+ $('#preview_' + selector).fadeOut("fast", function () {\r
+ $('#preview_' + selector).remove();\r
+ $('#profile-rotator').hide();\r
+ });\r
+\r
+ });\r
+ };\r
+\r
+ var trim = function(str) {\r
+ return str.replace(/^\s+|\s+$/g, "");\r
+ };\r
+ var escapeHTML = function(unsafe_str) {\r
+ return unsafe_str\r
+ .replace(/&/g, '&')\r
+ .replace(/</g, '<')\r
+ .replace(/>/g, '>')\r
+ .replace(/\"/g, '"')\r
+ .replace(/\[/g, '[')\r
+ .replace(/\]/g, ']')\r
+ .replace(/\'/g, '''); // ''' is not valid HTML 4\r
+ }\r
+\r
+ // Initialize LinkPreview \r
+ init();\r
+\r
+ return {\r
+ // make crawlText() accessable from the outside.\r
+ crawlText: function (text) {\r
+ crawlText(text);\r
+ }\r
+ };\r
+ };\r
+\r
+ $.fn.linkPreview.defaults = {\r
+ defaultDescription: "Enter a description",\r
+ defaultTitle: "Enter a title"\r
+ };\r
+})(jQuery);\r
--- /dev/null
+var linkPreview;
+
+$(document).ready(function() {
+ linkPreview = $('#profile-jot-text').linkPreview();
+});
+
+
+/**
+ * Insert a link into friendica jot.
+ *
+ * @returns {void}
+ */
+function jotGetLink() {
+ var currentText = $("#profile-jot-text").val();
+ var noAttachment = '';
+ reply = prompt(aStr.linkurl);
+ if(reply && reply.length) {
+ // There should be only one attachment per post.
+ // So we need to remove the old one.
+ $('#jot-attachment-preview').empty();
+ $('#profile-rotator').show();
+ if (currentText.includes("[attachment") && currentText.includes("[/attachment]")) {
+ noAttachment = '&noAttachment=1';
+ }
+
+ // We use the linkPreview library to have a preview
+ // of the attachments.
+ linkPreview.crawlText(reply + noAttachment);
+ autosize.update($("#profile-jot-text"));
+ }
+}
+
+/**
+ * Get in a textarea the previous word before the cursor.
+ *
+ * @param {object} text Textarea elemet.
+ * @param {integer} caretPos Cursor position.
+ *
+ * @returns {string} Previous word.
+ */
+function returnWord(text, caretPos) {
+ var index = text.indexOf(caretPos);
+ var preText = text.substring(0, caretPos);
+ // If the last charachter is a space remove the one space
+ // We need this in friendica for the url preview.
+ if (preText.slice(-1) == " ") {
+ preText = preText.substring(0, preText.length -1);
+ }
+// preText = preText.replace(/^\s+|\s+$/g, "");
+ if (preText.indexOf(" ") > 0) {
+ var words = preText.split(" ");
+ return words[words.length - 1]; //return last word
+ }
+ else {
+ return preText;
+ }
+}
+
+/**
+ * Get in a textarea the previous word before the cursor.
+ *
+ * @param {string} id The ID of a textarea element.
+ * @returns {sting|null} Previous word or null if no word is available.
+ */
+function getPrevWord(id) {
+ var text = document.getElementById(id);
+ var caretPos = getCaretPosition(text);
+ var word = returnWord(text.value, caretPos);
+ if (word != null) {
+ return word
+ }
+
+}
+
+/**
+ * Get the cursor posiotion in an text element.
+ *
+ * @param {object} ctrl Textarea elemet.
+ * @returns {integer} Position of the cursor.
+ */
+function getCaretPosition(ctrl) {
+ var CaretPos = 0; // IE Support
+ if (document.selection) {
+ ctrl.focus();
+ var Sel = document.selection.createRange();
+ Sel.moveStart('character', -ctrl.value.length);
+ CaretPos = Sel.text.length;
+ }
+ // Firefox support
+ else if (ctrl.selectionStart || ctrl.selectionStart == '0') {
+ CaretPos = ctrl.selectionStart;
+ }
+ return (CaretPos);
+}