what does "event =&gt" does in RxJS? - javascript

I came across this code below but I don't understand why we are doing event is equal and greater than and then console.log
I would really appreciate if someone explains it
const node = document.querySelector('input[type=text]');
const input$ = Rx.Observable.fromEvent(node, 'input');
input$.subscribe({
next: event => console.log(`You just typed ${event.target.value}!`),
error: err => console.log(`Oops... ${err}`),
complete: () => console.log(`Complete!`),
});
const input$ = Rx.Observable.fromEvent(node, 'input')
.map(event => event.target.value)
.filter(value => value.length >= 2)
.subscribe(value => {
// use the `value`
});

This looks like Javascript code that's been passed through an HTML sanitizer.
The original code using arrow functions should be as follows:
const node = document.querySelector('input[type=text]');
const input$ = Rx.Observable.fromEvent(node, 'input');
input$.subscribe({
next: event => console.log(`You just typed ${event.target.value}!`),
error: err => console.log(`Oops... ${err}`),
complete: () => console.log(`Complete!`),
});
const input$ = Rx.Observable.fromEvent(node, 'input')
.map(event => event.target.value)
.filter(value => value.length >= 2)
.subscribe(value => {
// use the `value`
});

This is invalid JavaScript. =&gt should be => and what you're seeing is simply ES6's arrow functions.
This is a display bug in the page you're seeing. It probably stems from the fact that < and > in HTML text should be transformed into < and > so as not to cause parse errors with the same characters when they serve as tag opening and closing (as in <div>).

Related

Function returns undefined in cypress.io

The following code works fine in a test.
cy.get("table").find(`tr[data-index=0] > :nth-child(1)`).then($td => {
cy.get("input").type($td.text().trim() + "{enter}");
});
But this one, same code but wrapped in a function, won't
const getResult = () => {
cy.get("table", {timeout: 60000}).find(`tr[data-index=0] > :nth-child(1)`, {timeout: 60000}).then($td => {
return $td.text().trim()
});
}
it("query", () => {
cy.get("input").type(getResult() + "{enter}");
})
what am I missing about then() in cypress?
The aim is, of course, getting the content of the first cell of the table and type it in input field.
EDIT:
following #jean-smaug suggestion, I tried this invoke/as
but I'm getting the error Cannot read property 'text' of undefined. Indeed the function is in a different ES module and the context is different. The code:
// different ES module
export const getResult = () => {
cy.get("table").find(`tr[data-index=0] > :nth-child(1)`).invoke("text").as("text")
}
// test
getResult("opencga-file-grid")
cy.get("input").type(this.text + "{enter}");
Your last example works if you drop the alias and treat the return value as a Cypress Chainable.
// different ES module
export const getResult = () => {
return cy.get("table").find(`tr[data-index=0] > :nth-child(1)`).invoke("text");
}
// test
getResult("opencga-file-grid")
.then(text => {
cy.get("input").type(text + "{enter}");
});
Equivalent to this (if all code was in the same file)
cy.get("table").find(`tr[data-index=0] > :nth-child(1)`).invoke("text")
.then(text => {
cy.get("input").type(text + "{enter}");
});
The problem is how to access variable in Cypress.
This part of the doc should be helpfull
https://docs.cypress.io/guides/core-concepts/variables-and-aliases.html#Sharing-Context
I guess you can do something like this
cy.get("table", {timeout: 60000}).find(`tr[data-index=0] > :nth-child(1)`, {timeout: 60000}).invoke('text').as('text')
cy.get("input").type(this.text + "{enter}");

Elements only appear after I input something

For some reason, everything is being initialized properly when I load the page for the first time, except for the paymentID and Amount, which are being display only after I click on something or input anything in a text box.
This is my code which initializes my webpage.
created: function () {
// Initializing persons
AXIOS.get('/persons')
.then(response => {
this.persons = response.data;
this.persons.forEach(person => this.getRegistrations(person.name))
this.persons.forEach(person =>
person.eventsAttended.forEach(event => {
this.getPaymentofRegistrations(person.name, event.name)
}))
})
.catch(e => {this.errorPerson = e});
.
.
.
.
getRegistrations: function (personName) {
AXIOS.get('/events/person/'.concat(personName))
.then(response => {
if (!response.data || response.data.length <= 0) return;
let indexPart = this.persons.map(x => x.name).indexOf(personName);
this.persons[indexPart].eventsAttended = [];
response.data.forEach(event => {
this.persons[indexPart].eventsAttended.push(event);
});
})
.catch(e => {
e = e.response.data.message ? e.response.data.message : e;
console.log(e);
});
},
getPaymentofRegistrations: function (personName, eventName) {
AXIOS.get('/registrations?person='+personName+'&event='+eventName)
.then(response => {
if (!response.data || response.data.length <= 0) return;
let indexPart1 = this.persons.map(x => x.name).indexOf(personName);
let indexPart2 = this.persons[indexPart1].eventsAttended.map(x => x.name).indexOf(eventName);
this.persons[indexPart1].eventsAttended[indexPart2].paymentId = response.data.bitcoin.userID;
this.persons[indexPart1].eventsAttended[indexPart2].paymentAmount = response.data.bitcoin.amount;
})
.catch(e => {
console.log(e)
})
}
Images attached for a better understanding of the problem.
It only takes writing a letter in a text box (without even clicking on a reactive button) for the Payment and Amount info to appear:
This code is very complex and hard to understand but if I should make a bid Vue.set can help for you:
https://v2.vuejs.org/v2/guide/reactivity.html#For-Objects
or you can store eventsAttended collections in another data property, not as a nested object.

How to avoid If and else in spread operator Javascript

I am quite new to JS. I am trying to simplify my code but its throwing me an syntax error. Is there any way I can avoid multiple codes like not using If and else statement. Below is the code I posted for reference.
the only difference is item.href.replace statement will have "?".
(() => {
const test = 'x=abc';
if (location.search == "") {
[...document.querySelectorAll('a')]
.filter(link => link.href.includes(test))
.forEach(item => (item.href = item.href.replace(`${test}`, location.search)));
} else {
[...document.querySelectorAll('a')]
.filter(link => link.href.includes(test))
.forEach(item => (item.href = item.href.replace(`?${test}`, location.search)));
}
})();
You can simply assign the string you want before the operation.
const test = 'x=abc';
let search = (location.search == "") ? test : `?${test}`;
[...document.querySelectorAll('a')]
.filter(link => link.href.includes(test))
.forEach(item => (item.href = item.href.replace(search, location.search)));
Well, the actual clean solution would be:
[...document.querySelectorAll('a')]
.filter(link => link.href.includes(test))
.forEach(link => link.search = link.search.replace(test, location.search));
We can approach this refactoring through 3 steps:
Move the document.querySelectorAll('a') to the top
Filter the resulting <a> tags that match our criteria through our selector through the ~= selector
Return the results in our function
The resulting code might look something like this:
const replaceQueryParams = function(test) {
const matchingLinks = [...document.querySelectorAll(`a[href~="${test}"]`)];
return matchingLinks.map((link) => link.href = link.href.replace(`?${test}`, window.location.search));
};
We can then use the replaceQueryParams function like so:
const replacedLinkStrings = replaceQueryParams("my-test-string");
if (replacedLinkStrings.length > 0) {
console.log("Do something here");
}

In Slate.js editor.apply(operation) is not applying "split_node" operations correctly

I am designing a google-doc like collaborative tool with latest React + Slate as Frontend and Flask in Backend. I am using socket-io in React and flask_socketio in Python to emit and listen content from other collaborators.
React app code:
const RichTextExample = props => {
const [value, setValue] = useState(props.currentEditor);
const editor = useMemo(() => withHistory(withReact(createEditor())), []);
const id = useRef(`${Date.now()}`);
const remote = useRef(false);
const socketchange = useRef(false);
useEffect(() => {
socket.on("new-remote-operations", ({ editorId, ops, doc_id }) => {
if (id.current !== editorId && doc_id === props.document.doc_id) {
remote.current = true;
JSON.parse(ops).forEach(op => {
console.log("LISTEN: applying op", op);
editor.apply(op);
});
remote.current = false;
console.log('value is ', value);
socketchange.current = true; //variable to track socket changes in editor via operations
}
});}, [])
return(
<Slate
editor={editor}
value={value}
onChange={value => {
setValue(value);
const ops = editor.operations
.filter(o => {
if (o) {
return o.type !== "set_selection" && o.type !== "set_value";
}
return false;
});
if (ops.length && !remote.current && !socketchange.current) {
console.log("EMIT: Editor operations are ", ops);
socket.emit("new-operations", {
editorId: id.current,
ops: JSON.stringify(ops),
doc_id: props.document.doc_id
});
}
socketchange.current = false;
}}
>
Python code for socket is simple:
app = Flask(__name__)
db_name = 'userdoc.db'
app.config['SECRET_KEY'] = 'secret-key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'+db_name
socketio = SocketIO(app, cors_allowed_origins="*")
#socketio.on('new-operations', namespace='/')
def operations(data):
print('operations listened...1/2/3..')
emit('new-remote-operations', data, broadcast=True, include_self=False)
Issue:
When split_node is passed as an type of operation in socket.on(),
editor.apply(op) doesn't apply it as it suppose to. Please help me on this.
Because of this, I get following two cases:
I think the issue you are facing is because you send a batch of operations that should not be applied one by one.
A split_node operation like the one you are generating by hitting enter will actually split all the nested nodes till it reaches the leaves, and move some nodes around.
Concretely, a split_node is actually 2-3 operations following each others, that can't be applied solely. If you apply the first one for example, that would split the text node, and end up with two Text sharing the same attributes. Slate will normalize them and re-merge them as soon as it can, which in your case, happen between each editor.apply(op).
I think the solution here, is simply to wrap your whole loop inside the withoutNormalizing method. It will prevent Slate to normalize the document in-between the operations.
For Slate <= 0.47
editor.withoutNormalizing(() => {
JSON.parse(ops).forEach(op => {
editor.apply(op);
});
})
For Slate >= 0.5
Editor.withoutNormalizing(editor, () => {
JSON.parse(ops).forEach(op => {
editor.apply(op);
});
})

Unable to iterate over an array

I am testing out the nodejs modules x-ray and cheerio
Following is my code:
const Xray = require("x-ray");
const cheerio = require('cheerio');
const xray = new Xray();
xray('https://news.ycombinator.com/', 'body#html')((err, result) => {
const $ = cheerio.load(`<body>${result}</body>`);
const elements = $('body')
.find('*')
.filter((i, e) => (
e.type === 'tag'
))
.map((i, e) => {
e.foo = {
id: i
};
return e;
})
.filter((i, e) => (
e.foo.id % 2 === 0
));
const elementsArray = elements.toArray();
console.log('Length of the array is:', elementsArray.length);
elementsArray.forEach((e) => {
console.log('I appear to print only once, even though elementsArray has lots of elements');
});
});
Issue here is the the console.log() inside the forEach loop prints only once - even though the output of the earlier console.log(elementsArray.length) is about 369.
Runkit link to test it out
I checked the type of elementsArray and I get Array or array as the type. Why then does the loop run only once?
The message is shown many times, but the console will consolidate (what's in a word) repetitions of the same message into one line with a counter next to it.
If you would change the message to make it unique every time, you'd see the difference.
For instance, if you would use the index in the message:
elementsArray.forEach((e,i) => {
console.log(i); // different message on every iteration
});
See the difference with the updated script on runkit.com

Categories