xul-Get selection html - 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();

Related

footer.replaceText() does not replace my placeholder with new text

Can anyone explain why footer.replaceText() does not replace my placeholder with new text. It works for both header and body.
//opens the master report document which is now saved as the student's name and gets the contents of the header
let header = DocumentApp.openById(documentId).getHeader()
//opens the master report document which is now saved as the student's name and gets the contents of the body
let body = DocumentApp.openById(documentId).getBody()
//opens the master report document which is now saved as the student's name and gets the contents of the footer
let footer = DocumentApp.openById(documentId).getFooter()
header.replaceText('{{First Name}}', row[studentDetails.firstName])
body.replaceText('{{Maths Attainment}}', row[studentDetails.mathsAttainment])
footer.replaceText('{{Class Teacher}}', row[studentDetails.classTeacher])
I can't seem to find an answer on Stack Overflow that works.
If you're using the option 'Different first page' you can't get the footer and header of the first page in the common (documented) way.
Based on this answer try to get them this 'secret' way:
let first_header = header.getParent().getChild(3);
let first_footer = header.getParent().getChild(4);
And then you can change them as usual:
first_header.replaceText('{{First Name}}', row[studentDetails.firstName]);
first_footer.replaceText('{{Class Teacher}}', row[studentDetails.classTeacher]);
I would like to give credit to Mr. Amit Agarwal who has provided a working solution to above.
The code is below:
const replaceHeaderFooter = () => {
// Returns the document with the specified ID
const doc = DocumentApp.openById('DOCUMENT ID');
// Retrieves the headers's container element which is DOCUMENT
const parent = doc.getHeader().getParent();
for (let i = 0; i < parent.getNumChildren(); i += 1) {
// Retrieves the child element at the specified child index
const child = parent.getChild(i);
// Determine the exact type of a given child element
const childType = child.getType();
if (childType === DocumentApp.ElementType.HEADER_SECTION) {
// Replaces all occurrences of a given text in regex pattern
child.asHeaderSection().replaceText('{{Company}}', 'Digital Inspiration');
} else if (childType === DocumentApp.ElementType.FOOTER_SECTION) {
// Replaces all occurrences of a given text in regex pattern
child.asFooterSection().replaceText('{{Copyright}}', '© Amit Agarwal');
}
}
// Saves the current Document.
// Causes pending updates to be flushed and applied.
doc.saveAndClose();
};
Thank you!

Adding two javascript functions(depending on input)

I have put together a calculator what calculates a price, depending on user input. It works fine with one input, but now I have to scale it a little with a second user input. But here's the catch: the user might not want to put anything to the field, so it will be empty. And that's the thing that brakes my code. I could duplicate the calculator function and return the values and add those two together in a third function, but it will not work when there's an empty value.
Just for the sake of it, some trivial HTML code:
//When I only calculate with this user input, its easy
<input type="text" id="rocktext"><br>
// But how to consider this and do the same exact calculations like with the
//first one and add those two result together?
<input type="text" id="rocktext2"><br>
The code in the end should look like:
Take first user input, calculate the price(like in code below)
IF(!!) there is a second user input, calculate the price and add it to
the first one
Am I being a moron to try it with JS or just a moron in the firstplace?
Hope to hear from You, guys!
J.
The initial JS code is as follows:
function priceCalc() {
var inputs = document.getElementById("rocktext").value;
var length = inputs.length;
var accept = 6;
var initPrice = 8;
if (inputs<=accept){
// Since the code is much simpler right now i just put the result in HTML as follows:
document.getElementById("rockpricetotal").innerHTML = initPrice + " dollars";
//I can also return the the value calculated here like so:
//retVal = initPrice;
}
else {
var intLength = parseInt(length, 10);
var lengthGap = intLength - accept;
var totals = lengthGap * 0.8 + initPrice;
var prec = totals.toPrecision(3);
// Since the code is much simpler right now i just put the result in HTML as follows:
document.getElementById("rockpricetotal").innerHTML = prec + " dollars";
// Here also the return clause can be possible with the calculation result like so:
//retVal = prec;
}
// And the final return as an alternative to the innerHTML :
// return retVal;
}
Making it scalable, you can add a class to all the inputs which may be in the function (something like calcInput), so you iterate all of them and if the value isn't empty (and if it's a valid number), you put it in the calculation.
Or you can just verify if the second input is empty, if so, calls functionOne, if not, calls functionTwo:
function twoDifferentWays() {
var valueOne = document.querySelector("#rocktext").value;
var valueTwo = document.querySelector("#rocktext2").value;
if (!!valueTwo && !isNaN(valueTwo)) {
callsFunctionOne(valueOne, valueTwo);
} else {
callsFunctionTwo(valueOne, valueTwo);
}
}

Is there a simple way to have a local webpage display a variable passed in the URL?

I am experimenting with a Firefox extension that will load an arbitrary URL (only via HTTP or HTTPS) when certain conditions are met.
With certain conditions, I just want to display a message instead of requesting a URL from the internet.
I was thinking about simply hosting a local webpage that would display the message. The catch is that the message needs to include a variable.
Is there a simple way to craft a local web page so that it can display a variable passed to it in the URL? I would prefer to just use HTML and CSS, but adding a little inline javascript would be okay if absolutely needed.
As a simple example, when the extension calls something like:
folder/messageoutput.html?t=Text%20to%20display
I would like to see:
Message: Text to display
shown in the browser's viewport.
You can use the "search" property of the Location object to extract the variables from the end of your URL:
var a = window.location.search;
In your example, a will equal "?t=Text%20to%20display".
Next, you will want to strip the leading question mark from the beginning of the string. The if statement is just in case the browser doesn't include it in the search property:
var s = a.substr(0, 1);
if(s == "?"){s = substr(1);}
Just in case you get a URL with more than one variable, you may want to split the query string at ampersands to produce an array of name-value pair strings:
var R = s.split("&");
Next, split the name-value pair strings at the equal sign to separate the name from the value. Store the name as the key to an array, and the value as the array value corresponding to the key:
var L = R.length;
var NVP = new Array();
var temp = new Array();
for(var i = 0; i < L; i++){
temp = R[i].split("=");
NVP[temp[0]] = temp[1];
}
Almost done. Get the value with the name "t":
var t = NVP['t'];
Last, insert the variable text into the document. A simple example (that will need to be tweaked to match your document structure) is:
var containingDiv = document.getElementById("divToShowMessage");
var tn = document.createTextNode(t);
containingDiv.appendChild(tn);
getArg('t');
function getArg(param) {
var vars = {};
window.location.href.replace( location.hash, '' ).replace(
/[?&]+([^=&]+)=?([^&]*)?/gi, // regexp
function( m, key, value ) { // callback
vars[key] = value !== undefined ? value : '';
}
);
if ( param ) {
return vars[param] ? vars[param] : null;
}
return vars;
}

Varying the string in an HTML label or text control

Looking for an elegant and quick way to vary/rotate (rotate as in change value, not change orientation) the contents of an html Label (or textbox).
For example, on our website we would like a caption to sometimes say "Our Database Products are Great", other times have it populate with "Helping Small Businesses since 2004" etc. The chosen string can be randomly selected from a set list, but should vary every time the web page is reloaded (ok if the same one comes up more than once in a row).
What would be an easy way to accomplish this? Is there a quick way to do it without Java?
Java is the easy way.
add a div and then update it with text every few seconds.
var text = ["My text 1", "My text 2", "My text 3"];
var value = 0;
var elem = document.getElementById("div id");
setInterval(change, 1000);
function change() {
elem.innerHTML = text[counter];
value++;
if(value >= text.length) { value = 0; }
}
You can simply use JavaScript (if you can rely on your users having JavaScript). Add an id to the HTML element which will store the message, and add the following JavaScript code (replacing randommessage with you id) and adding any other messages to the messages array.
messages = ["Our Database Products are Great", "Helping Small Businesses since 2004", "Some other message"];
document.getElementById("randommessage").innerHTML = messages[Math.floor(Math.random()*messages.length)]
Live JSFiddle example
<html>
<head>
<script>
function myFunction() {
var cars = ["Saab", "Volvo", "BMW"];
var randomCar = cars[Math.floor(Math.random() * cars.length)];
alert(randomCar);
document.getElementById('randomName').innerHTML = randomCar;
}
</script>
</head>
<body onload="myFunction()">
<label id="randomName"></label>
</body>
</html>

Google Documents: set heading as defined in current document

I'm writing a script that picks the paragraph where the cursor is contained, set the text to uppercase and change the paragraph heading to HEADING1.
However, the paragraph is set to the 'global' HEADING1, not to HEADING1 as it is defined in the current document. Here is the code.
function SetSceneHeading() {
var cursor = DocumentApp.getActiveDocument().getCursor();
var element = cursor.getElement();
var paragraph = [];
if (element.getType() != 'PARAGRAPH') {
paragraph = element.getParent().asParagraph();
}
else paragraph = element.asParagraph();
var txt = paragraph.getText();
var TXT = txt.toUpperCase();
paragraph.setText(TXT);
paragraph.setHeading(DocumentApp.ParagraphHeading.HEADING1);
}
Is there a way to set a paragraph to the 'current' HEADING1? Thanks.
I found a workaroud to set a paragraph to a user defined heading. Basically, you first set the heading using setHeading(), then you set to "null" the attributes that the previous operation messed up. This way the paragraph is set according to the user defined heading.
function MyFunction ()
var paragraph = ....
paragraph.setHeading(DocumentApp.ParagraphHeading.HEADING1);
paragraph.setAttributes(ResetAttributes());
function ResetAttributes() {
var style = {};
style[DocumentApp.Attribute.FONT_SIZE] = null;
style[DocumentApp.Attribute.BOLD] = null;
style[DocumentApp.Attribute.SPACING_BEFORE] = null;
style[DocumentApp.Attribute.SPACING_AFTER] = null;
return style;
}
I made a few tests, FONT_SIZE BOLD SPACING_BEFORE SPACING_AFTER seem to be the attributes that need to be reset. They may be more, according to the cases.
Unfortunately it seems that this won't be possible for now, there is an open issue that I think is relevant : issue 2373 (status acknowledged) , you could star it to get informed of any enhancement.