How can get current element without id and class? - javascript

I use an editable QWebView and write some text on it. I want to get current element that text cursor point to it and do some changes. For example text cursor is in a <p> tag that haven't any Id or class. I want to get this paragraph and set it's display to none for example.
How can I get the current element that haven't any Id or class?
I tried: this.style.display="none" it didn't work, but when I try document.getElementsByTagName('p')[0].style.display="none" it works. And I don't know how can i get the current element.
Point that I want to do this just with javascript, not jquery. and without any click or etc. Is it possible? How can i do this?
How does execCommand work? for example how execCommand justifyRight get the current element?
This is my code:
QWebFrame *frame = p->webView->page()->mainFrame();
QString js = QString("this.style.display='none'");
frame->evaluateJavaScript(js);
Thank you

In the case of an editable web page, ideally we'd want to be able to ask the QWebFrame in what QWebElement is the caret, at any time. Then we could tweak this element with C++ code.
Unfortunately, according to the documentation, no such method is provided.
Anyway, there's a workaround in webkit's javascript since we can access the user selection or the caret's position in the DOM with window.getSelection(). Here's some code that finds the nearest <p> tag above the selection and changes its style as needed:
QString js=
" var node = window.getSelection().getRangeAt(0).startContainer;"
" while (node) {"
" if (node.nodeName.toUpperCase()=='P') {"
" node.style.display='none';"
" break;"
" }"
" node=node.parentNode;"
" }" ;
QVariant res = page()->mainFrame()->evaluateJavaScript(js);
You might want to generalize it to take node types and styles as parameters, and possibly test it a bit (I'm no JS expert), but the I believe the principle is sound.

Related

Can't get element by class when append()

I have this code in my project.
var quickmode_list = "";
quickmode_list += '<div style="height:100px;width:500px;margin-top:0%;margin-right:0%"value="'
+ quicksetup_item
+'"class="quickmode_block quick_list"><center style="margin-top:20px"><font size="5" style="margin-left:-14%;">'
+quicksetup_item
+'</font></center></div>';
<div id="quickmode_table">
</div>
and I append this variable to a tag like this
$('#quickmode_table').append(quickmode_list);
So, It does show out in browser and it show out as class = "quickmode_block", but when I do alert($('.quickmode_block').length);
It return me "0". How does it going wrong if there perform like class "quickmode_block" but I can't get it by class?
This is because the DOM tree did not manage to refresh between your two JavaScript instruction (appending and alerting).
Better solution would be to use element creators (they are in jQuery) and then you would have the handle to the new element out of the box, you can access it and count the amount of them. It is even more performance friendly than generating html strings and querying the tree.
If quicksetup_item does not end with space, there would be no space before the class attribute.
According to HTML specification (https://www.w3.org/TR/html5/syntax.html#start-tags): "Attributes must be separated from each other by one or more space characters.". Sometimes, browser will tolerate this syntax error by inserting space automatically between attributes. In that case, code will run successfully.
However, it is recommended to follow the HTML specification and add spaces, rather than rely on browser tolerance.

Change Spotfire Document Properties value using javascript

I want to Change the value assigned to a Document Property in spot fire. Lets say i have created a new document property called "Test1" as a string and assign it a value "a". Is there are way to change this value using Javascript every time i load the spotfire dashboard ?
I'm unaware of a way to use JavaScript for this, but you can assign a string document property via custom expression (if it's a List Box) or run an IronPython script each time the value changes. So, you could set the expression to the current date, datetimenow() and then every time it's loaded the IronPython script would fire. However, I don't see why you'd need the property control for this.
I suppose it really depends on what you want the document property to be set to. Is it data from your tables? Output from complex code? These are all things to consider.
1) Create an input type property control using the Document Property you want to change.
2) Edit Html to assign parent element an id say "testInput". And add the script as shown below in the Edit HTML window.
<span id="testInput"><SpotfireControl id="7db34e6c423240f59fc99e6b80fa23ec" /></span>
<script>
$("#testInput input").val("after");
$("#testInput input").focus();
$("#testInput input").blur();
</script>
3) This script will change the document property value to "after" whenever you open a file.
As you comment seemed to suggest, something you can do is write this code in Python and attach the script to an action control, e.i. a Link or a Button. Something simple like: Document.Properties["Test1"] = newValue
or even: Document.Properties[changingProperty] = newValue
allowing the code to be more reusable.
Then you insert Javascript into the Text Area as well to the effect of: $("#VeryLongSpotfireControlID").click();
Which should simulate clicking on action control, which in turn triggers the Python script to update the value. Just be careful not to use this approach when it would result in reloading the text area HTML, as this will re-trigger the Javascript, thus creating an endless loop.
I believe I have found a possible solution/work-around for the issue, entirely based on pure JavaScript (since TIBCO removed jQuery starting from Spotfire X). The solution is to force a simulated Enter Keystroke while focusing the input box to trigger updating the Document Property. (No data function and R needed)
HTML (SpotfireControl Element is an single line input-box for a Doc. Prop.):
<div id="container"><SpotfireControl id="b8534f13dc62416db6d4eaab16030f5e" /></div>
JS (focus and blur might no longer be needed for this solution, but I'm still keeping them just in case):
const inputConfirmationEvent = new KeyboardEvent("keypress", {
    keyCode: 13,
    bubbles: true,
    cancelable: false
});
var elem = document.querySelector("#container input");
elem.value = "stringValue";
elem.blur();
elem.focus();
document.querySelector("#container input").dispatchEvent(inputConfirmationEvent);
Hope it helps someone.
Best,
Aaron

Inserting a popup DOM node into WYSIWYG

I am trying to add a clickable div to the sceditor. The basic requirement is to use a wysiwyg and programmatically add an element into the editor, which can display a popup when the user clicks on it.
To do this I use:
var text = "<div onClick='editdiv(this)'>"+name+"</div>";▓
$('.sceditor').sceditor('instance').insert(text);
This inserts the div into the editor but when I click on it, I get an error saying editdiv is not defined. Whereas editdiv is a function present inside the javascript same javascript file which runs the above code.
Can someone please tell me what am I doing wrong and/or a way to achieve what I want? Thanks!
What you want is impossible to get without drawbacks.
Events can only be caught inside an active browsing instance (I think that's the name). Everything inside a contentEditable=true" is not an active browsing instance
Based on that, You need to terminate the contentEditable and make a new one inside. For example (code not tested):
var text = "<div contentEditable='false' onclick='editdiv(this)'><div contentEditable='true'>"+name+"</div></div>";
$('.sceditor').sceditor('instance').insert(text);
That should make that click event work as expected

document.write to display content on same page.

I have a doubt with javascript document.write method. Mostly when I use document.write() it shows me the content written with the method in a different page. For instance, if I write the command like this, document.write("Hello, My name is Sameeksha"); then the execution of this line takes me to a different document on the same page. I want to be able to append the message on the same page, with other elements of the page. For example, if I have text boxes and buttons on the page and I want the text with document.write to appear under all the content of the page or on a particular section of a page. Please suggest what can be done to get the output in this way? As, this way it will be really easy to create dynamic HTML content.
Thank you so much for your time.
Regards,
Sameeksha Kumari
document.write is basically never used in modern Javascript.
Whan you do instead is to create explicit DOM elements and append them to the document in the place you want. For example
var x = document.createElement("div"); // Creates a new <div> node
x.textContent = "Hello, world"; // Sets the text content
document.body.appendChild(x); // Adds to the document
Instead of appending to the end you can also add child nodes to any existing node. For example:
function addChatMessage(msg) {
var chat = document.getElementById("chat"); // finds the container
var x = document.createElement("div");
x.textContent = msg;
chat.appendChild(x);
}
I'd say 6502 posted the more correct way to do it, but I think someone should mention innerHTML as well. First, give some element in your HTML body an id so you can reference it:
<div id="outputDiv">I'm empty.</div>
Then, either at the bottom of your document (at the end of the <body> tag), or any other time after the page is loaded, you can update the contents with innerHTML:
document.getElementById("outputDiv").innerHTML = "<h1>Hello!!!</h1>";
Here's a jsfiddle demonstrating this. This isn't as clean/correct/elegant as using the more standard DOM methods, but it's well supported. Sometimes quick and dirty is what you need!

Get text offset from click event via Javascript?

So I have searched all over trying to figure out how to do the following and have yet to find a solution:
I need to get the text offset for a given HTML element from a click event. This means that if I have the following HTML
<p>This is a really cool paragraph</p>
and a user clicks on the first 'a' in the sentence, the text offset would be 8 seeing as the first 'a' is at index 8 if we take the 'T' in 'This' as index 0.
I need this information so that I may programmatically create a text selection based on where a user clicks. As of right now I can track which HTML elements are clicked on and thus I can create this sort of activity at a HTML-element level granularity, but I'd like to have finer control than that.
Thank you!
Copied from your comment in another answer:
I'm currently trying to simulate human behavior via Javascript which
is turning out to be a bit more difficult than I anticipated (most
likely by design).
What you want is Selenium, for web browser automation: http://seleniumhq.org/
Using Prototype:
<p id='mytext'>This is a really cool paragraph</p>
<script type='text/javascript'>
var characters = $('mytext').textContent;
var newchars = '';
for(I = 0;I < chars.length;I++) {
newchars += '<span id="char_' + I + '">' + chars[I] + '</span>';
}
$('mytext').textContent = newchars;
Event.observe($('mytext'), 'click', function(e) {
var spanID = (e.findElement('span')).getAttribute('id')
var index = spanID.split('_')[1]; // Ta-daaa!
});
</script>
Please don't do this for large blocks of text (or, preferably, at all). It creates a DOM node for every character, and can slow the browser down...
I don't think there's anything built in for that. Any solution will be a hack and unreliable.
What you can do is use the selection API to get a user selection on a page, which sounds like you can do.
Just throwing this out there as a possible hack/solution.
You could try using the mouse offsetX and offsetY when a click occurs and simulate a double click dblclick in that location, effectively selecting the text and then using the selection API to get the word they clicked. Wouldn't work to the letter, but might work to the word.
Append each letter inside a span tag and onClick event just extract the letter inside the span tag and may be keep reference with some attributes in the span tag for tracking the index of the position for each of the element.But this approach would be redundant.
Try window.getSelection() ...I'm not sure if it works in all browsers, but at least Chrome seems to create a Selection object with the offset you need.

Categories