Hello i have small problem with nicedit editor
the problem is
the first line is can not be affected !
example :
i writed ( asdad ) in the first line of the textarea box
i marked it and clicked on ( center align )
it's should go to the center of the box
see this picture
this problem is only in first line ..
others is work fine
The problem is only in firefox !
i am using firefox 3..... and i see this problem !
my code is
<script src="http://js.nicedit.com/nicEdit-latest.js" type="text/javascript"></script>
<script type="text/javascript">bkLib.onDomLoaded(nicEditors.allTextAreas);</script>
<textarea cols=40 rows=10></textarea>
Thank you !
I also had that problem. And we are not alone:) It is nicEditor's bug http://nicedit.com/forums/viewtopic.php?f=4&t=364&p=848&#p848. And looks like it isn't fixed yet.
I've solved this bug by using TinyMCE-editor :) And if you are not tied with nicEditor I would suggest to look on TinyMCE.
I hope it will be helpfull.
I have developed a solution for this.
The problem is the first line that is not in a div.
This will fix it
$(document).ready(function () {
$('.nicEdit-main').bind('DOMSubtreeModified',function(){
nicEditFirstLinePatch();
});
});
and
function nicEditFirstLinePatch(){
function placeCaretAtEnd(el) {
el.focus();
if (typeof window.getSelection != "undefined"
&& typeof document.createRange != "undefined") {
var range = document.createRange();
range.selectNodeContents(el);
range.collapse(false);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (typeof document.body.createTextRange != "undefined") {
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
textRange.collapse(false);
textRange.select();
}
}
textNode=$('.nicEdit-main').contents().filter(function(){
return this.nodeType == 3;
})[0];
$('.nicEdit-main').attr('id','toHandle');
if(textNode){
var newNode = document.createElement('div');
var newNodeContent = document.createTextNode(textNode.nodeValue);
newNode.appendChild(newNodeContent);
var parentNode=document.getElementById('toHandle');
parentNode.replaceChild(newNode,textNode);
var range = document.createRange();
range.setStart(newNode,0);
}
if(document.getElementById('toHandle').children.length==1){
placeCaretAtEnd(document.getElementById("toHandle"));
}
}
It works fine on Chrome 55.0.2883.87. I think it's crossbrowser but I'm not sure. however it is a good start :)
Related
This must have been a very generic question but I have not come across any concrete or stable solution for this.
I just want to fetch the number of words in a web page but across all the browsers. My current implementation is
var body = top.document.body;
if(body) {
var content = body.innerText || body.textContent;
content = content.replace(/\n/ig,' ');
content = content.replace(/\s+/gi,' ');
content = content.replace(/(^\s|\s$)/gi,'');
if(!body.innerText) {
content = content.replace(/<script/gi,'');
}
console.log(content);
console.log(content.split(' ').length);
}
This works well but it does not work with some Firefox browsers as innerText does not work on Firefox.
If I use textContent then it displays the contents of JS tags too if present. Eg if a web page content is
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
console.log('Hellow World');
var some = "some";
var two = "two";
var three = "three";
</script>
<h1 style="text-align:center">Static content from Nginx</h1>
<div>
This is a
static.
<div>
This is a
static.
</div>
</div>
</body>
Then textContent will have JS code too in the content which will give me wrong word count.
What is the concrete solution that can work across any environment.
PS: No JQuery
Ok, you have there two problems:
Cross-browser innerText
I'd go with:
var text = document.body[('innerText' in document.body) ? 'innerText' : 'textContent'];
That, to prefer innerText over textContent.
Stripping result of <script> tags.
dandavis offers a neat solution to that:
function noscript(strCode){
var html = $(strCode.bold());
html.find('script').remove();
return html.html();
}
And a non-jQuery solution:
function noscript(strCode){
return strCode.replace(/<script.*?>.*?<\/script>/igm, '')
}
A function that will turn the string into a "fake" html document, strip its script tags and return the raw result.
Of course, you may improve the function to remove also <style> tags and others.
Counting letters
Your method to do the job is alright, but still, I think that a simple regex would do the job much better. You can count the words in a string using:
str.match(/\S+/g).length;
Finally
Final result should look like
var body = top.document.body;
if(body) {
var content = document.body[('innerText' in document.body) ? 'innerText' : 'textContent'];
content = noscript(content);
alert(content.match(/\S+/g).length);
}
What about hidden/invisible/overlayed blocks? do you want to count words inside all of it? what about images (alt tag of image)
if you want to count all - just strip tags and count test of all rest blocks. smth like that $('body :not(script)').text()
Thank you so much for giving such a helpful answers. I found this approach to use if the innerText is not defined in a browser. And the result that we get is very much similar to innerText. Hence I think it will be consistent across all the browsers.
All of you please look into it and let me know if this answer can be accepted. And let me know if you guys find any discrepancy in this method I am using.
function getWordCount() {
try {
var body = top.document.querySelector("body");
if (body) {
var content = body.innerText || getInnerText(top.document.body, top);
content = content.replace(/\n/ig, ' ');
var wordCount = content.match(/\S+/gi).length;
return wordCount;
}
} catch (e) {
processError("getWordCount", e);
}
}
function getInnerText(el, win) {
try {
win = win || window;
var doc = win.document,
sel, range, prevRange, selString;
if (win.getSelection && doc.createRange) {
sel = win.getSelection();
if (sel.rangeCount) {
prevRange = sel.getRangeAt(0);
}
range = doc.createRange();
range.selectNodeContents(el);
sel.removeAllRanges();
sel.addRange(range);
selString = sel.toString();
sel.removeAllRanges();
prevRange && sel.addRange(prevRange);
} else if (doc.body.createTextRange) {
range = doc.body.createTextRange();
range.moveToElementText(el);
range.select();
}
return selString;
} catch (e) {
processError('getInnerText', e);
}
}
The result that I am getting is same as that of innerText and is more accurate than using regex, or removing tags etc.
Please give me ur views on this.
I have tried anything to get the selected text for a context menu, but it is not working in IE11.
For context menu adding I have added some code in registry, and a htm file with a Javascript.
First I have tried this:
var parentwin = external.menuArguments;
var doc = parentwin.document;
var sel = doc.selection;
var rng = sel.createRange();
var selectedtext = new String(rng.text);
then I have read in IE11 documentation, the document.selection has been repalced in the API with window.getSelection();
So I have tried any variant, window.getSelection... nothing works...
Any idea how I can access the selected text?
And I have searching also how I can copy to the clipboard.. in chrome I have used this script:
function copyToClipboard(text){
var copyDiv = document.createElement('div');
copyDiv.contentEditable = true;
document.body.appendChild(copyDiv);
copyDiv.innerHTML = text;
copyDiv.unselectable = "off";
copyDiv.focus();
document.execCommand('SelectAll');
document.execCommand("Copy", false, null);
document.body.removeChild(copyDiv);
}
Finally I have found the solution: (tested in IE11)
var parentwin = external.menuArguments
var selectedText = getSel();
function getSel(){
var w=window,d=parentwin.document,gS='getSelection';
return (''+(w[gS]?w[gS]():d[gS]?d[gS]():d.selection.createRange().text)).replace(/(^\s+|\s+$)/g,'');
}
parentwin.console.log("the selected text is:"+sel);
copyToClipboard(selectedText);
function copyToClipboard(s) { //only works in IE :(
if (window.clipboardData && clipboardData.setData) {
clipboardData.setData('text', s);
}
}
I'm developing a mobile banking application and I'm interested in formatting the currency amount inputs in real time.
I've already tested autoNumeric plugin and jQuery Format Currency Plugin but both have cursor position issues on Android 2.* browsers.
Does anyone have a JavaScript solution compatible with this browsers?
I don't know about autoNumeric, but http://code.google.com/p/jquery-formatcurrency/ looks pretty good. The jsFiddle example you posted doesn't place the caret correctly on my desktop browser, but this does, and on my (Jellybean) Android phone as well. (On Gingerbread, the blinking cursor bar may jump to the end of the line, but you will still be editing where it last was.) Try their demo: http://www.bendewey.com/code/formatcurrency/demo/format_as_you_type.html
I usually use accounting.js
You can download it from http://openexchangerates.github.io/accounting.js/#download
It's quite easy to use. You can see how it works from that same download page.
I created a couple javascript functions which i use to do the cursor management:
function formatMoney(myField){
if(myField.selectionStart || myField.selectionStart == '0'){
var len = myField.value.length;
var caretPos = doGetCaretPosition(myField);
myField.value = accounting.formatMoney(myField.value);
var newlen = myField.value.length;
setCaretPosition(myField, newlen != len ? (newlen > len ? caretPos + 1 : caretPos - 1) : caretPos);
}
}
function doGetCaretPosition (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);
}
function setCaretPosition(elem, caretPos) {
elem.value = elem.value;
if(elem != null) {
if(elem.createTextRange) {
var range = elem.createTextRange();
range.move('character', caretPos);
range.select();
}
else {
if(elem.selectionStart) {
elem.focus();
elem.setSelectionRange(caretPos, caretPos);
}
else
elem.focus();
}
}
}
You can use the functions with the text field as:
<input id="myField" type="text" onkeyup="formatMoney(this);" onChange="formatMoney(this);" onBlur="formatMoney(this);" />
The getting and the setting caret position functions were gotten from here: Set keyboard caret position in html textbox
I tested it on Android 2.1 emulator. Though the emulator was slow but it seemed to be working. You can find the screenshot here: https://www.dropbox.com/s/9ximuwh64kadiea/shot.JPG?dl=0
Here's an open source, well contributed, well commited library : https://github.com/plentz/jquery-maskmoney
Seems to answers your need, doesn't it ?
Havent't tested it under Android though.
It seems this jQuery plugin - NumBox - aims to provide solution to your problem.
Here is the code I got from Full text search in HTML ignoring tags / & and it is not highlighting in case of Mozilla..
function doSearch(text) {
if (window.find && window.getSelection) {
document.designMode = "on";
var sel = window.getSelection();
sel.collapse(document.body, 0);
// Till here works in Mozilla But the below line is not matching even if the text is found in window. But works fine in Google Chrome
while (window.find(text)) {
document.getElementById("button").blur();
document.execCommand("HiliteColor", false,"yellow");
sel.collapseToEnd();
}
document.designMode = "off";
} else if (document.body.createTextRange) {
var textRange =document.body.createTextRange();
while (textRange.findText(text)) {
textRange.execCommand("BackColor", false,"yellow");
textRange.collapse(false);
}
}
}
Is there any alternative mode to deal with Mozilla?
Please have a look at this and suggest if any code need to be needed.
Actually i am trying to set the cursor to a specific node inside a html editor (which uses a contenteditable iframe). For example i have several paragraphs and want the cursor to move to the start of the previous paragraph.
Unfortunatly, the Internet Explorers range object does not support setStartBefore and setStartAfter. The ierange project is not an option - the solution i am looking for needs to work with IE out of the box.
How do i set the cursor in IE?
In Firefox the solution is straight forward:
// sets the cursor position (start defines, if cursor is needed at the start or end of the node)
function setCursor(editor, node, start){
var tn = editor.getDoc().createTextNode("."); // gets the editors document
if (start){
node.insertBefore(tn, node.firstChild);
}
else node.appendChild(tn);
rng = editor.selection.getRng(); // gets the browsers range object for the users selection
rng.selectNode(tn);
rng.setStartBefore(tn);
rng.setStartAfter(tn);
ed.selection.setRng(rng);
node.removeChild(tn); // removes the caret node - curser is placed now
}
You could use my Rangy project for this. The code would then be the same in all browsers:
function setCursor(element, start) {
var doc = element.ownerDocument || element.document;
var win = doc.defaultView || doc.parentWindow;
rangy.init();
var range = rangy.createRange(doc);
range.selectNodeContents(element);
range.collapse(start);
rangy.getSelection(win).setSingleRange(range);
}
Alternatively, this particular case isn't too tricky without a library:
function setCursor(element, start) {
var doc = element.ownerDocument || element.document;
if (typeof doc.createRange != "undefined") {
var range = doc.createRange();
range.selectNodeContents(element);
range.collapse(start);
var win = doc.defaultView || doc.parentWindow;
var sel = win.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (typeof doc.body.createTextRange != "undefined") {
var textRange = doc.body.createTextRange();
if (start) {
textRange.moveToElementText(element);
textRange.collapse(start);
} else {
var markerEl = doc.createElement("span");
markerEl.innerHTML = "\u00A0";
element.appendChild(markerEl);
textRange.moveToElementText(markerEl);
element.removeChild(markerEl);
}
textRange.select();
}
}
Working with the Cursor Position
(This solution works for me in IE, Firefox and Opera)