Find caret position inside element - html

I have a span inside the contenteditable div and I need to figure out if the cursor is in the last position on the span tag. I looked in the Selection and Range solutions but couldn't figure out a straight forward way to achieve that.
<html>
<script>
var selection = window.getSelection();
var range = selection.getRangeAt(0);
//this is what I am trying to achive
var selection_target = range.selectNodeContents(document.getElementById('target'));
var length = selection_target.toString().length;
</script>
<body>
<div id='target' contenteditable='true'>
<span>some text(figure cursor position here)</span>
</div>
</body>
</html>

For the case in the question where the span only has one child that is a text node, you can check whether the caret is at the end of it as follows:
Demo: http://jsfiddle.net/Wm5Hz/
Code:
var span = document.getElementById("target").getElementsByTagName("span")[0];
var spanTextNode = span.lastChild;
var sel = window.getSelection();
var isCaretAtEndOfSpan = (sel.isCollapsed
&& sel.focusNode == spanTextNode
&& sel.focusOffset == spanTextNode.data.length);
Things are slightly more complicated in the general case: the same visual position can be represented in different ways (e.g. after the last character in the text node, after the text node itself, after the end of the span), plus if the span could contain elements then you'd need to find the last text node within the span and compare the selection against it. Also, none of this works in IE < 9, which has a completely different API.

Related

tlfTextField - Highlight a part of text with "Code"

I wonder how to set the text "Highlight" of a part of text inside tlfTextField with the code?
I tried "tf.backgroundColor = 0x990000" property, but did not help.
For instance, I can change the Font Color of any contents inside Parenthesis, by this code:
private function decorate():void {
var tf:TextFormat = new TextFormat();
tf.color = 0x990000;
var startPoint:int = 0;
while (startPoint != -1) {
var n1:int = textMc.tlfText.text.indexOf("(", startPoint);
var n2:int = textMc.tlfText.text.indexOf(")", n1 + 1);
if (n1 == -1 || n2 == -1) {
return;
}
textMc.tlfText.setTextFormat(tf, n1 + 1, n2);
startPoint = n2 + 1;
}
}
So I know "tf.color = 0x990000;" will change the Font color, however, don't know how to "highlight" some text, with code, as I do inside Flash manually.
You should have probably used tlfMarkup property to set the required format to the specific part of text. The attributes you seek are backgroundColor and backgroundAlpha of the span XML element that you should wrap your selection, however it should be much more difficult should there already be spans around words when you retrieve the property from your text field.
The problem with your solution is that you don't check if the two characters are located on a single line before drawing your rectangle, also you would need to redraw such rectangles each time something happens with the textfield. The proposed approach makes use of Flash HTML renderer's capabilities to preserve the formatting, however it will require a lot of work to handle this task properly.

Can you target a specific element among the results of a css selector independent of it's location? or relation? [duplicate]

This question already has an answer here:
Matching the first/nth element of a certain type in the entire document
(1 answer)
Closed 7 years ago.
Given some css selector that returns a set of matching elements from the document. Is there any way within css to take the resulting set and target the nth result?
nth-of-type and nth-child pseudoclasses will not work to my understanding because they will not treat all possible matches as a linear list. Such as:
<div>
<span class="aClass" /> <!-- found by :nth-of-type(1) -->
<span class="aClass" /> <!-- found by:nth-of-type(2) -->
<div>
<span class="aClass" /> <!-- found by :nth-of-type(1) -->
</div>
I want to be able to treat all these occurrences as a linear list of 3 elements, and target one of them independently of where in the document they may be located.
I don't think this is possible as you described it. A general rule of CSS is that queries can delve deeper, and occasionally they can move "sideways" along the tree through a set of neighbors (and for that matter, only in one direction), but they can never take information from one node, traverse upward, go into a neighbor, and apply that information to another node. An example:
<div>
<div class="relevant">
<!-- *whistles spookily* - "Zis WILL be the last time you see me!" -->
</div>
<span class="myCssTarget"></span>
</div>
The comment in that HTML is a space that is, for all intents and purposes, "invisible" to myCssTarget. If I added any HTML inside of there, then it could never directly affect the span outside.
I could offer further suggestions if you offer a specific situation, but this may be either a call for a redesign of the components you're putting in, or perhaps a JavaScript-based solution.
I just saw some clarification to the question. Here is a much simpler fiddle to get all spans with "aClass" into a list that will let you target the nTh span. Still using Jquery instead of CSS.
https://jsfiddle.net/h2e0xgwf/6/
$(document).ready(function(){
var nTh = 5; // change this to whichever N you wish
var allSpans = $("div > span.aClass");
$(allSpans[nTh-1]).html($(allSpans[nTh-1]).html() + " : found the " + nTh + "th element").css("background-color", "blue").css("color","white");
});
I know that there is no way to do that within CSS. You can select the nth element of the given class name with JavaScript
var elem = getElementsByClassName('.aClass').item(n-1)
or with jQuery
var elem = $('.aClass').toArray().filter(function(elem, i){
return i==(n-1);
})[0];
If I understood you correctly you want a linear list of all spans that have class="aClass" who are direct children of a div.
Which means that in your example you will have 2 list of spans, the first list will have 2 elements and the second list will have 1.
You then wish to change the style of all nth children; for example changing the firsts' style would cause 2/3 spans to be affected: the two directly under a new div. And if you were to change the second child, only 1/3 spans would be affected.
If that is what you are looking for I don't believe it can be done in CSS but it can be done in JQuery. I created a fiddle with an example just in case my understanding of your question was correct.
https://jsfiddle.net/h2e0xgwf/4/
$(document).ready(function(){
var nTh = 3; // change this to whichever N you wish
var rowsOfSpans = new Array();
var divsWithChildren = $("div:parent");
for(var i = 0; i < divsWithChildren.length; i++){
rowsOfSpans[i] = $(divsWithChildren[i]).children("span.aClass");
}
for(var i = 0; i < rowsOfSpans.length; i ++){
for(var j =0; j < rowsOfSpans[i].length; j++){
if(j == nTh-1){
// THIS IS THE NTH ELEMENT
$(rowsOfSpans[i][j]).html($(rowsOfSpans[i][j]).html() + " : found the " + nTh + "th element").css("background-color", "blue").css("color","white");
}
}
}
});

Resizing floated first div's based on second floated div contents?

I want to have to floated columns side-by side. If second column has contents then the first column should resize its content based on the second column, is that possible with CSS? Widths are not defined.
It's possible using javascript but not with straight CSS. Here are some ways to do it:
Using javascript:
var rightDiv = document.getElementById("straightJ2");
var rightWidth = rightDiv.clientWidth;
var leftDiv = document.getElementById("straightJ1");
if($('#straightJ2').text() || rightDiv.hasChildNodes()) {
leftDiv.style.width = rightWidth + "px";
}
Or more minimal (and possibly overwhelming/hard to follow) javascript:
if($('#minimal2').text() || $('#minimal2').firstChild) {document.getElementById("minimal1").style.width = document.getElementById("minimal2").clientWidth + "px";}
Using jQuery:
if($('#secondColumnId').html() != '')
{
$('#firstColumnId').width($('#secondColumnId').width());
}
Each of these check the second div for text or a child element and change the width of the first if one of those conditions is met
All examples can be found used in this jsFiddle

Proper way to use style attributes

I'm using DocumentApp.Attribute with mixed results. Here is an example:
var underline = {};
underline[DocumentApp.Attribute.UNDERLINE] = true;
underline[DocumentApp.Attribute.WIDTH] = 100;
underline[DocumentApp.Attribute.MARGIN_LEFT] = 10;
doc.appendParagraph("Paragraph text").setAttributes(underline);
The paragraph is created, and underlined, but the other two attributes don't get applied.
I think that you will find that a paragraph cannot have either Margin or width attributes ... they apply to the page or document as a whole. You might get the effect that you wish by using the Indent set of attributes.
This begs the next question "how do you set page attributes?"
MARGIN-LEFT appears as an attribute of the Body section so getActiveSection().setAttributes(style)
I am not sure what width refers to but you can do a getAttributes for each element type to track it down PAGE-WIDTH is an attribute of Body Section again. Play around with this code ...
function myFunction() {
var doc = DocumentApp.openById("1lqjkdfdsafgdsafsdaQI3kjtY");
var docele = doc.getActiveSection();
Logger.log(docele.getAttributes());
var para = doc.getParagraphs()[0];
var atts = para.getAttributes();
Logger.log(atts)
// Define a custom paragraph style.
var style = {};
style[DocumentApp.Attribute.WIDTH] = 100;
style[DocumentApp.Attribute.MARGIN_LEFT] = 200;
docele.setAttributes(style);
}
For me this gave body section attributes of {UNDERLINE=null, MARGIN_BOTTOM=72.0, PAGE_HEIGHT=792.0, BOLD=null, BACKGROUND_COLOR=null, FONT_SIZE=null, FONT_FAMILY=null, STRIKETHROUGH=null, MARGIN_LEFT=10.0, PAGE_WIDTH=612.0, LINK_URL=null, ITALIC=null, MARGIN_RIGHT=72.0, MARGIN_TOP=72.0, FOREGROUND_COLOR=null}
and paragraph attributes of {UNDERLINE=null, INDENT_END=8.25, LEFT_TO_RIGHT=true, BOLD=null, BACKGROUND_COLOR=null, FONT_SIZE=12, FONT_FAMILY=Comic Sans MS, SPACING_BEFORE=null, SPACING_AFTER=null, STRIKETHROUGH=null, INDENT_START=0.0, LINE_SPACING=null, LINK_URL=null, ITALIC=null, INDENT_FIRST_LINE=0.0, HORIZONTAL_ALIGNMENT=null, HEADING=null, FOREGROUND_COLOR=null}
This gives a clue to the alternative form for setting of attributes
docele.setAttributes({"FOREGROUND_COLOR":"#ff0000"})

xul-Get selection html

I have the following function that is supposed to get HTMLs for the user selected area on the web page. This function does not seems to work properly.
Sometime, it gets htmls which is not selected also.
Can anyone please look into this function? -- Thanks a lot.
//----------------------------Get Selected HTML------------------------
function getSelectionHTML(){
if (window.getSelection)
{
var focusedWindow = document.commandDispatcher.focusedWindow;
var sel = focusedWindow.getSelection();
var html = "";
var r = sel.getRangeAt(0);
var parent_element = r.commonAncestorContainer;
var prev_html = parent_element.innerHTML;
if(prev_html != undefined)
{
return prev_html;
}
return sel;
}
return null;
}
It looks to me like you're getting the contents of the parent element rather than the selection itself. If the parent element contains anything other than what you have selected, then you'll get that too.
var sel = focusedWindow.getSelection();
This line returns a selection object. It contains the exact text selected by the user. You then get the range from the selection and get the commonAncestorContainer. So if you have code like this:
<div id="ancestor">
<p>First sentence.</p>
<p>Another sentence.</p>
</div>
And your user selects from the 's' of the first sentence to the 's' of the second sentence then the commonAncestorContainer is the div element so you'll also get the rest of the text.
A good reason for this would be if you wanted to guarantee yourself a valid HTML fragment (this seems to be the case, implied by your function name), but if you just want the selected text then call the toString method on the range directly:
var focusedWindow = document.commandDispatcher.focusedWindow;
var sel = focusedWindow.getSelection();
var r = sel.getRangeAt(0);
return r.toString();