/**
* Helper function to click dropdowns and select the passed text option
*
* #param {Selector} selector - Selector that picks the select web element
* #param {string} text - Text value option to be selected
*/
async function selectDropDownOption(selector, text) {
let option = selector.find("option");
await t.scrollIntoView(selector).click(selector).click(option.withExactText(text));
}
Question: this is for text option but can we do it for "Select web element"?
Related
I want to override the functionality of an HTMLElement so that the scrollTop property, on get or set, will do some extra logic before touching the actual value. The only way, as far as I have found, is to delete the original property and then use Object.defineProperty():
delete element.scrollTop;
Object.defineProperty(element, "scrollTop", {
get: function() : number {
...
},
set: function(value: number) {
...
}
});
However, this removes all access to the original scrollTop, so the new logic can't do something like return base.scrollTop. The comments on this older, similar question claim that getting access to the original value is not possible when overriding with Object.defineProperty().
I'm wondering if a possible alternative is to create an adapter class that implements the HTMLElement interface and wraps the HTMLElement in question. All implemented properties delegate to the wrapped element's properties, but its scrollTop would do the extra work I need.
I'm quite new to Typescript, but is the alternative possible? If so, is there a lightweight way of defining all other properties on the adapter that we're not touching to automatically delegate to the wrapped element?
Here is my solution to the problem (which is a bit more tricky than might seem)
I implemented some utility for that and usage look like:
Let's say we want to replace some div 'scrollTop' method to return 50 if scrollTop is bigger than 50 and return original value if it is less than 50:
const div = document.createElement("div")
replaceOriginalPropertyDescriptor(div, "scrollTop", (originalDescriptor, div) => {
return {
// Keep rest of the descriptor (like setter) original
...originalDescriptor,
get() {
const originalScrollTop = originalDescriptor.get!.apply(div);
if (originalScrollTop > 50) return 50;
return originalScrollTop
},
}
})
Here is implementation with bunch of comments:
/**
* Will replace property descriptor of target while allowing us to access original one.
*
* Example:
*
* Will replace div.scrollTop to return 50, if original scrollTop is bigger than 50. Otherwise returns original scrollTop
*
* const div = document.createElement("div")
*
* replaceOriginalPropertyDescriptor(div, "scrollTop", (originalDescriptor, div) => {
* return {
* get() {
* const originalScrollTop = originalDescriptor.get.apply(div);
*
* if (originalScrollTop > 50) return 50;
*
* return originalScrollTop
* },
* // Keep rest of the descriptor (like setter) original
* ...originalDescriptor,
* }
* })
*/
function replaceOriginalPropertyDescriptor<T extends object>(
input: T,
property: keyof T,
newDescriptorCreator: (originalDescriptor: PropertyDescriptor, target: T) => PropertyDescriptor
) {
const originalDescriptor = findPropertyDescriptor(input, property);
if (!originalDescriptor) {
throw new Error(`Cannot replace original descriptor ${String(property)}. Target has no such property`);
}
const newDescriptor = newDescriptorCreator(originalDescriptor, input);
Reflect.defineProperty(input, property, newDescriptor);
}
What was my use case:
I am using drag and drop library that is reading scroll positions like 500 times a second. I wanted to cache this value for lifetime of a single frame. As I cannot control source code of the library itself, I am kinda injecting this cache to HTMLElements itself so they keep previous scroll position values for 1 frame.
Is there a way I can replace the 2nd character in a cell with an asterisk(*)?
Something like this:
var name = publicWinners.getRange(i, 1);
name.setValue( → 2nd character = "*" ← );
I want to create a list of winners in a contest that can be posted publicly with the winners' personal information partially hidden.
Any help would be greatly appreciated. Thank you!
Use String.replace :
/*<ignore>*/console.config({maximize:true,timeStamps:false,autoScroll:false});/*</ignore>*/
const str = "John Doe";
const output = str.replace(/(.{1})./,"$1*");
console.info(output);
<!-- https://meta.stackoverflow.com/a/375985/ --> <script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
. - Any character
(.{1}) - Any character repeated 1 time. {1} may be removed, but used to quantify previous characters, if you want to replace the third or fourth character. Capture group$1
. - Final character to replace with *
You can use the split() and join() methods to manipulate the string.
/**
* Replace a character of a string with a new character at the specified position.
* #param {string} word - The word to modify.
* #param {number} index - The character index to modify. Starts from zero.
* #param {string} newChar - The new character that will overwrite the existing character.
* #returns {string}
*/
function replaceCharAt(word, index, newChar) {
return word.split('').map(function(char, charIndex) {
if (charIndex == index) {
return newChar;
}
return char;
}).join('');
}
A simple test you can run:
var originals = [
'Sangmyeong',
'Jaedong',
'Sangjin',
'Gueho'
];
originals.forEach(original => console.log(replaceCharAt(original, 1, '*'))); // [S*ngmyeong, J*edong, S*ngjin, G*eho]
function replaceCharAt(word, index, newChar) {
return word.split('').map(function(char, charIndex) {
if (charIndex == index) {
return newChar;
}
return char;
}).join('');
}
I want to disable no_superfluous_phpdoc_tags rule.
/**
* Refund a list of payments.
*
* #param float $amount
* #param array $charges
*
* #throws PaymentException
*
* #return boolean
*
*/
With the rule defaults it turns the above into this.
/**
* Refund a list of payments.
*
* #throws PaymentException
*
*/
I tried this:
./vendor/bin/php-cs-fixer fix -vvv --rules='{"no_superfluous_phpdoc_tags": {"allow_unused_params": "true"}}'
But it doesn't affect the result (still removes the params). What can I do to not remove these params?
In the php_cs.dist file:
'no_superfluous_phpdoc_tags' => false,
or in the console:
vendor/bin/php-cs-fixer fix .php_cs.dist --rules='{"no_superfluous_phpdoc_tags": false}'
Or how hyperlink of google docs looks like in raw format.
I tried to do the next thing:
var links;
var nameArr = ["1", "2", "3", "4", "5", "6"];
var tempArr= ["11", "12", "13", "14", "15", "16"];
for (i = 0; i < nameArr.length; i++) {
nameArr[i].setUrlLink("https://en.wikipedia.org/wiki/" + tempArr[i] + "/detection"
links = links + ", "+ nameArr[i];
}
I get an error, as i can't use setLinkUrl on string, only on text object - didn't find a way to cast string into text.
Although, if i paste it "as it", the "http..." shows as a regular string - not a link.
I Want to get something like this:
1, 2, 3 ...... and paste it into google docs document.
Links are "rich" features of the associated element (usually Text). So to add a link to generic text, first you must get the associated Text element, and then invoke setLinkUrl on it.
As with other rich format methods, appended elements inherit the formatting specification of the preceding sibling element. Thus, if you format the last element of a parent, the next element appended to the parent will likely also be formatted in that manner. I explicitly specify a nullstring URL for the separator text to avoid the link extending beyond the actual display text. (This means that if you programmatically append to the Paragraph after calling this function, that appended text will have the same URL as the last display text from your array.)
This simple function takes a Paragraph as input, along with the array of display text and the URIs, and adds them to the end.
/**
* Create links at the end of the given paragraph with the given text and the given urls.
* #param {GoogleAppsScript.Document.Paragraph} pg The paragraph to hold the link array
* #param {string[]} values The display text associated with the given links
* #param {string[]} links The URI for the given link text
* #param {string} [separator] text that should separate the given links. Default is comma + space, `", "`
* #returns {GoogleAppsScript.Document.Paragraph} the input paragraph, for chaining
*/
function appendLinkArray(pg, values, links, separator) {
if (!pg || !values || !links)
return;
if (!values.length || !links.length || values.length > links.length)
throw new Error("Bad input arguments");
if (separator === undefined)
separator = ", ";
// Add a space before the link array if there isn't one at the end of any existing text.
if (pg.getText() && (!pg.getText().match(/ $/) || !pg.getText().match(/ $/).length))
pg.appendText(" ").setLinkUrl("");
// Add each link display text as a new `Text` object, and set its link url.
links.forEach(function (url, i) {
var text = values[i] || url;
pg.appendText(text)
.setLinkUrl(0, text.length - 1, url);
if (separator && i < links.length - 1)
pg.appendText(separator).setLinkUrl("");
});
return pg;
}
Looking at this chart:
I would like to extract the volume information at a given point in time (the volume is shown in the chart title, when the cursor is moved across the volume chart) – e.g:
[Fri. Jul 26, 2013 13:25:00] Volume 118
which is stored on the chart as:
< area shape="rect" coords="541,463,542,471" onmousemove="showStudyTooltip(event, 'B', '[Fri. Jul 26, 2013 13:25:00]', 'Volume', '118.0000000')" >
How can this been done?
Note that it is not only 'Volume' that I want to extract, but also different indicator values that can be added beneath the volume chart.
PS Among others I have search for inspiration the following places (but been unable to come up with a solution):
Does Google Apps Script have something like getElementById?
http://www.distilled.net/blog/distilled/guide-to-google-docs-importxml/
The data you're looking for isn't really well-formed for automated extraction, but we can work with it. The getElementByVal() function from this answer can be refactored to create getElementsByVal(), which will return an array of all matching document elements, giving us something to do further searching in.
/**
* Traverse the given XmlElement, and return an array of matches.
* Note: 'class' is stripped during parsing and cannot be used for
* searching, I don't know why.
* <pre>
* Example: getElementsByVal( body, 'input', 'value', 'Go' ); will find
*
* <input type="submit" name="btn" value="Go" id="btn" class="submit buttonGradient" />
* </pre>
*
* #param {XmlElement} element XML document element to start search at.
* #param {String} id HTML <div> id to find.
*
* #return {[XmlElements]} All matching elements (in doc order).
*/
function getElementsByVal( element, elementType, attr, val ) {
var results = [];
// If the current element matches, remember it.
if (element[attr]
&& element[attr] == val
&& element.getName().getLocalName() == elementType) {
results.push( element );
}
// Check element's children
var elList = element.getElements();
var i = elList.length;
while (i--) {
// (Recursive) Check each child, in document order.
results = results.concat(getElementsByVal( elList[i], elementType, attr, val ));
}
// Return summary of matches
return results;
}
To make use of this new helper function, what if we create a function getIndicators() that accepts a String parameter containing the point in time we're interested in - Mon. Jul 29, 2013 07:40:00 for example? The matching text will be found in an area element that's got shape="rect", and we'll find it inside an attribute called onmousemove. Here's our function:
function getIndicators(timeString) {
var txt = UrlFetchApp.fetch("http://www.barchart.com/chart.php?sym=DXU13&t=BAR&size=M&v=2&g=1&p=I:5&d=L&qb=1&style=technical&template=").getContentText();
var doc = Xml.parse(txt,true);
var body = doc.html.body;
var indicators = "not found";
// Look for elements matching: < area shape="rect" ... >
var chartPoints = getElementsByVal(body, 'area', 'shape', 'rect');
// Search for the chartPoint with tooltip containing the time we care about
for (var i=0; i<chartPoints.length; i++) {
if (chartPoints[i].onmousemove.indexOf(timeString) > -1) {
// found our match
indicators = chartPoints[i].onmousemove;
}
}
return indicators
}
As it stands, it will return the entire text value assigned to onmousemove; the exercise of parsing that intelligently is left to you.
Here's a test function to help:
function test_getIndicators() {
Logger.log( getIndicators("Mon. Jul 29, 2013 07:40:00" ) );
}
When run, here's the log (today, anyway...):
[13-07-29 16:47:47:266 EDT] showOHLCTooltip(event, 'B', '[Mon. Jul 29, 2013 07:40:00]', 'DXU13', '81.8050000', '81.8300000', '81.8000000', '81.8200000')