RadEditor scrolls to top after pasting the contents - javascript

I am using Telerik RadEditor.
The issue:
On pasting the content into the Telerik Radeditor, the editor is getting scrolled to top. So, I searched the internet and also Telerik forums, but no luck. Finally, I worked on the following code with fix.
Code for RadEditor Server-Side Control:
<telerik:RadEditor
ID="E"
runat="server"
Width="100%"
AllowScripts="true"
AllowPaging="true"
EnableResize="false"
NewLineMode="P"
OnClientLoad="OnClientLoad"
OnClientModeChange="E_OnClientModeChanged"
EditModes="Design,Html"
StripFormattingOptions="Span,MsWordRemoveAll,CSS,Font,ConvertWordLists"
OnClientPasteHtml="radEditorControl_OnClientPasteHtml"
OnClientSelectionChange="OnClientSelectionChange">
</telerik:RadEditor>
Below is the Javascript Code with fix:
//Event on pasting the content into the RadEditor. Fixing the scrolling issue on pasting the content.
var isPasted = false;
function radEditorControl_OnClientPasteHtml(editor, args) {
if (editor != undefined)
isPasted = true;
}
function OnClientSelectionChange(editor, args) {
if (isPasted != undefined && isPasted == true && editor != undefined) {
isPasted = false;
editor.setFocus();
var iframeElement = editor._contentAreaElement; // the DOM element for the iframe;
if (iframeElement) {
//Get the iFrame cursor position.
var _focusNode = iframeElement.contentWindow.getSelection().focusNode;
if (_focusNode != undefined) {
//Focus node is not an element, get the previous element sibling
if (_focusNode.nodeType != 1) {
if (_focusNode.previousElementSibling != undefined)
_focusNode = _focusNode.previousElementSibling;
else
_focusNode = _focusNode.parentNode;
}
//Insert a div near focusNode(cursor) of the iFrame contentWindow.
var timeStamp = new Date().getUTCMilliseconds();
var _id = "scrollArea_" + timeStamp;
var focusElement = jQuery('<input type="text" id="' + _id + '" name="' + _id + '" onfocus="alert();" />').insertAfter(_focusNode)[0];
setTimeout(function () {
if (focusElement != undefined) {
focusElement.focus({ preventScroll: true });
focusElement.select();
var range = editor.getSelection().getRange(true); //returns an object that represents a restore point.
editor.getSelection().selectRange(range);
if (range != undefined && range.collapse !=undefined)
range.collapse(true);
jQuery(focusElement).replaceWith("");
}
}, 50);
}
}
}
}
The above code is working in IE and Chrome, but not in Firefox as focus() is not getting triggered for the input element which I am binding.
Please let me know if there is any other way for resolving the scroll issue on paste in RadEditor.

I am aware of such a problem within the older versions of RadEditor. My advice is to try the latest version which you can test at https://demos.telerik.com/aspnet-ajax/editor/examples/overview/defaultcs.aspx. If the problem still persists please drop us a line in the Telerik AJAX forums or via the support ticketing system and we will look deeper into it.

Related

Safari does not add a break when hitting enter

I want a user to be able to type in a content editable div, hit enter (or come to the end of the line) and have their text collected into a variable and have their cursor put on a new line, standard for any text editor. I have this event listner that checks for those conditions:
writerId.addEventListener('keydown', function(event){
if(event.key === "Enter" || document.getElementById("writer").offsetWidth >= "570") {
if(initialState === true) {
writtingContent = writerId.innerHTML;
blurId.innerHTML = writtingContent ;
writerId.innerHTML = "";
initialState = false;
} else {
writtingContent = writtingContent + writerId.innerHTML;
blurId.innerHTML = writtingContent ;
writerId.innerHTML = "";
}
}
});
The new line works in Chrome, FireFox but not Safari.
Initially I added this as a workaround for Safari:
if(navigator.userAgent.indexOf("Safari") != -1) {
writtingContent = writtingContent + "</br>";
console.log(navigator.userAgent);
}
But it broke things in other browsers (specifically Opera) and I've read that navigator.userAgent is not the best way to go about browser specific issues anyway.
I've seen some workarounds with feature detection but I'm not sure if that's necessary; I'd love if there was an easier way; something, perhaps, I've overlooked.

AJAX based search returning page information

I found the source of the error but do not know how to fix it. I'm using codeigniter and I'm trying to make a textbox with search results showing under it to help the user find what they are looking for. Think similar to google's search. When I make the AJAX call, it's returning everything on the webpage as well as the search results.
Example of issue: https://gyazo.com/244ae8f3835233a2690512cebd65876d
That textbox within the div should not be there as well as the white space. Using inspect element I realized the white spaces are my links to my CSS and JS pages. Then there's the textbox which is from my view.
I believe the issue lies within my JS.
//Gets the browser specific XmlHttpRequest Object
function getXmlHttpRequestObject() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
} else {
alert("Your Browser Sucks!\nIt's about time to upgrade don't you think?");
}
}
//Our XmlHttpRequest object to get the auto suggest
var searchReq = getXmlHttpRequestObject();
//Called from keyup on the search textbox.
//Starts the AJAX request.
function searchSuggest() {
if (searchReq.readyState == 4 || searchReq.readyState == 0) {
var str = encodeURI(document.getElementById('txtSearch').value);
searchReq.open("GET", '?search=' + str, true);
searchReq.onreadystatechange = handleSearchSuggest;
searchReq.send(null);
}
}
//Mouse over function
function suggestOver(div_value) {
div_value.className = 'suggest_link_over';
}
//Mouse out function
function suggestOut(div_value) {
div_value.className = 'suggest_link';
}
//Click function
function setSearch(value) {
document.getElementById('txtSearch').value = value;
document.getElementById('search_suggest').innerHTML = '';
}
//Called when the AJAX response is returned.
function handleSearchSuggest() {
if (searchReq.readyState == 4) {
var ss = document.getElementById('search_suggest');
ss.innerHTML = '';
var str = searchReq.responseText.split("\n");
for (i = 0; i < str.length - 1; i++) {
var suggest = '<div onmouseover="javascript:suggestOver(this);" ';
suggest += 'onmouseout="javascript:suggestOut(this);" ';
suggest += 'onclick="javascript:setSearch(this.innerHTML);" ';
suggest += 'class="suggest_link">' + str[i] + '</div>';
ss.innerHTML += suggest;
}
}
}
More specifically the getXmlHttpRequestObject function. it is returning the entire page including my header and footer. I don't believe any more info is needed but if anyone feels that way, I'll supply the view and controller.
https://gyazo.com/d0c43326191a4b09cc4b1d85d67a1bf6
This image shows the console and how the response and response text are the entire page instead of just the results.
Your call to the view method is loading the header view, the suggest view and the footer view while your suggest model is echoing the data that you're after.
You could just remove the line $this->view("suggest"); and your suggestions will be echoed.
This isn't great though. I would pass the titles back to the controller from the model then create a new controller method that outputs the data in a structured way (probably JSON).

body onload=func works in IsPost but not !IsPost (are multiple body-onloads okay)?

I have a script that is triggered with an If(IsPost) and an If(!IsPost). When I F11 through the code everything works the same expect at the end a javascript function to show a div does not trigger.
// SCRIPT FOR SHOW DIV.
<script>
function ShowFunction(divId)
{
$("#" + divId).show(600);
}
</script>
if (!IsPost)
{
var user = WebSecurity.CurrentUserId;
var dbCommand = "SELECT * FROM Survey WHERE survey_id = #0";
var row = db.QuerySingle(dbCommand, user);
if (row != null)
{
surv1 = row.surveyQ1;
if (surv1 != null)
{
someOtherVariable = "Complete";
<body onload="$('#somediv').remove();"></body>;
}
}
if (someOtherVariable = "Complete";
{
<body onload="ShowFunction('Mydiv');"</body>;
}
}
if (IsPost)
{
if (Request.Form["btnsubmit"] !=null)
{
var user = WebSecurity.CurrentUserId;
var dbCommand = "SELECT * FROM Survey WHERE survey_id = #0";
var row = db.QuerySingle(dbCommand, user);
if (row != null)
{
surv1 = row.surveyQ1;
}
if (surv1 == "yes")
{
<body onload="ShowFunction('Mydiv');"></body>;
}
}
}
Also, the cshtml page is structured with the script right above the !IsPost which is above the IsPost, which is above the Form code. Another post suggest that a 'window.onload' script, which I also have in my script block, might be messing with the < body onload="func" >. I'm not sure why that would be an issue only when not posting though.
I found the culprit. Although this wasn't in the original code I posted, I actually had one more body-onload bit of code right above the one that wasn't triggering in the if(!ispost). That extra body-onload wasn't in the if(ispost) which is why the post worked fine. I've edited the original code to show this. Once I moved that first body-onload (with some massaging) down into the other body-onload it worked fine. After moving that first body-onload down I am left with one body-onload in my if(!ispost) section of code.
<body onload="ShowFunction('Mydiv'); $('#somediv').remove();"</body>;
I also added appended my original title so that this might be useful for someone who stumbles upon it. In sum, watch out when you have multiple onload events. You might need to stack them into one onload and massage the code a bit.

Chrome Extension doesn't considers optionvalue until reloaded

I'm working on my first Chrome Extension. After learning some interesting notions about jquery i've moved to raw javascript code thanks to "Rob W".
Actually the extension do an XMLHttpRequest to a remote page with some parameters and, after manipulating the result, render an html list into the popup window.
Now everything is up and running so i'm moving to add some option.
The first one was "how many elements you want to load" to set a limit to the element of the list.
I'm using fancy-setting to manage my options and here's the problem.
The extension act like there's a "cache" about the local storage settings.
If i do not set anything and perform a clean installation of the extension, the default number of element is loaded correctly.
If i change the value. I need to reload the extension to see the change.
Only if a remove the setting i see the extension work as intended immediately.
Now, i'm going a little more into specific information.
This is the popup.js script:
chrome.extension.sendRequest({action: 'gpmeGetOptions'}, function(theOptions) {
//Load the limit for topic shown
console.log('NGI-LH -> Received NGI "max_topic_shown" setting ('+theOptions.max_topic_shown+')');
//Initializing the async connection
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://gaming.ngi.it/subscription.php?do=viewsubscription&pp='+theOptions.max_topic_shown+'&folderid=all&sort=lastpost&order=desc');
xhr.onload = function() {
var html = "<ul>";
var doc = xhr.response;
var TDs = doc.querySelectorAll('td[id*="td_threadtitle_"]');
[].forEach.call(TDs, function(td) {
//Removes useless elements from the source
var tag = td.querySelector('img[src="images/misc/tag.png"]'); (tag != null) ? tag.parentNode.removeChild(tag) : false;
var div_small_font = td.querySelector('div[class="smallfont"]'); (small_font != null ) ? small_font.parentNode.removeChild(small_font) : false;
var span_small_font = td.querySelector('span[class="smallfont"]'); (small_font != null ) ? small_font.parentNode.removeChild(small_font) : false;
var span = td.querySelector('span'); (span != null ) ? span.parentNode.removeChild(span) : false;
//Change the look of some elements
var firstnew = td.querySelector('img[src="images/buttons/firstnew.gif"]'); (firstnew != null ) ? firstnew.src = "/img/icons/comment.gif" : false;
var boldtext = td.querySelector('a[style="font-weight:bold"]'); (boldtext != null ) ? boldtext.style.fontWeight = "normal" : false;
//Modify the lenght of the strings
var lenght_str = td.querySelector('a[id^="thread_title_"]');
if (lenght_str.textContent.length > 40) {
lenght_str.textContent = lenght_str.textContent.substring(0, 40);
lenght_str.innerHTML += "<span style='font-size: 6pt'> [...]</span>";
}
//Removes "Poll:" and Tabulation from the strings
td.querySelector('div').innerHTML = td.querySelector('div').innerHTML.replace(/(Poll)+(:)/g, '');
//Modify the URL from relative to absolute and add the target="_newtab" for the ICON
(td.querySelector('a[id^="thread_title"]') != null) ? td.querySelector('a[id^="thread_title"]').href += "&goto=newpost" : false;
(td.querySelector('a[id^="thread_goto"]') != null) ? td.querySelector('a[id^="thread_goto"]').href += "&goto=newpost": false;
(td.querySelector('a[id^="thread_title"]') != null) ? td.querySelector('a[id^="thread_title"]').target = "_newtab": false;
(td.querySelector('a[id^="thread_goto"]') != null) ? td.querySelector('a[id^="thread_goto"]').target = "_newtab": false;
//Store the td into the main 'html' variable
html += "<li>"+td.innerHTML+"</li>";
// console.log(td);
});
html += "</ul>";
//Send the html variable to the popup window
document.getElementById("content").innerHTML = html.toString();
};
xhr.responseType = 'document'; // Chrome 18+
xhr.send();
});
Following the background.js (the html just load /fancy-settings/source/lib/store.js and this script as Fancy-Setting How-To explains)
//Initialization fancy-settings
var settings = new Store("settings", {
"old_logo": false,
"max_topic_shown": "10"
});
//Load settings
var settings = settings.toObject();
//Listener who send back the settings
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.action == 'gpmeGetOptions') {
sendResponse(settings);
}
});
The console.log show the value as it has been cached, as i said.
If i set the value to "20", It remain default until i reload the extension.
If i change it to 30, it remain at 20 until i reload the extension.
If something more is needed, just ask. I'll edit the question.
The problem appears to be a conceptual misunderstanding. The background.js script in a Chrome Extension is loaded once and continues to run until either the extension or the Chrome Browser is restarted.
This means in your current code the settings variable value is loaded only when the extension first starts. In order to access values that have been updated since the extension is loaded the settings variable value in background.js must be reloaded.
There are a number of ways to accomplish this. The simplest is to move the settings related code into the chrome.extension.onRequest.addListener callback function in background.js. This is also the most inefficient solution, as settings are reloaded every request whether they have actually been updated or not.
A better solution would be to reload the settings value in background.js only when the values are updated in the options page. This uses the persistence, or caching, of the settings variable to your advantage. You'll have to check the documentation for implementation details, but the idea would be to send a message from the options page to the background.js page, telling it to update settings after the new settings have been stored.
As an unrelated aside, the var keyword in the line var settings = settings.toObject(); is not needed. There is no need to redeclare the variable, it is already declared above.

Keep javascript within new javascript element

I am developing a webpage but I came into some trouble with some javascript code.
I am using the Nicedit as WYSIWYG for textareas, which, as stated in its main page, is as easy as copy/paste this 2 lines anywhere in my web page:
<script src="http://js.nicedit.com/nicEdit-latest.js" type="text/javascript"></script>
<script type="text/javascript">bkLib.onDomLoaded(nicEditors.allTextAreas);</script>
That's working great with the default textareas of the page. The problem is that I also have this javascript to add more textareas:
function addchapter()
{
if (num_chapter < 10)
{
var num=num_chapter+1;
document.getElementById('chapters').innerHTML += "<h3>Chapter " + num + "</h3> Title: <input type='text' name='titlechapter_" + num + "'><br>Content:<textarea name='chapter_" + num + "'></textarea>";
}
else if (num_chapter == 10)
{
document.getElementById('chapters').innerHTML += "<br />Maximum is 10 chapters.";
}
num_chapter += 1;
}
So when I add a textarea through javascript, it doesn't have the proper style; it's not implementing Nicedit. The thing is that the textareas are all standard, so there's no difference between the code in both cases. I don't know too much of javascript but I think that the problem might be that the Nicedit code runs ONCE when the page loads, and that's it. Any idea of how to make it run when the page loads (<= already done) AND when the addchapter function is run?
The relevant HTML bit is this:
<div id="chapters">
</div>
<button type="button" onclick="addchapter()"> Add chapter </button>
My page where you can see the odd behaviour is this (broken link), under Chapter 1 you see the 'Add chapter' button.
Thank you all so much.
EDIT 1, Error console output:
When the page loads it throws this:
"GET http://js.nicedit.com/nicEditIcons-latest.gif
bkClass.extend.getStylenicEdit-latest.js:8
bkClass.extend.constructnicEdit-latest.js:38
AnicEdit-latest.js:8
bkClass.extend.addInstancenicEdit-latest.js:37
bkClass.extend.panelInstancenicEdit-latest.js:37
nicEditors.allTextAreasnicEdit-latest.js:37
bkLib.domLoaded"
When I add a new chapter:
"Uncaught TypeError: Object #<bkClass> has no method 'removeInstance'
bkClass.extend.checkReplacenicEdit-latest.js:37
bkClass.extend.panelInstancenicEdit-latest.js:37
nicEditors.allTextAreasnicEdit-latest.js:37
(anonymous function)/file/new/:112
onclick"
You have to assign a unique ID to the text fields you add to the page. To convert it into an editor you can then call;
nicEditors.findEditor(editorID);
Or you can call nicEditors.allTextAreas() again. But I'm not sure if that will remove the existing content from the editors that already exist.
Source: The API.
You can add try{}catch(e){} block to your code
jQuery('.js-control-des').each(function () {
var index = jQuery(this).attr('lang');
var editor = jQuery(this).find('textarea');
var editor_id = editor.attr('id');
var editor_loaded = editor.attr('rel');
if (editor_loaded == undefined || editor_loaded != null || editor_loaded == 0) {
var editor_new_width = parseFloat(editor.css('min-width')) + 7 + 'px';
editor.css({
width: editor_new_width,
'max-width': editor_new_width,
'min-width': editor_new_width
});
try {
new nicEditor({maxHeight: 300}).panelInstance(editor_id);
jQuery(this).attr('rel', 'editor-loaded');
jQuery(this).find('.nicEdit-main').attr('data-index', index).keyup(function (e) {
if (vnLineUcp.editorKeyUp(jQuery(this)) == false) {
return false;
}
});
} catch (e) {
}
}
});

Categories

Resources