filterDescendants and findDescendant with slate.js - javascript

I'm working on making a wysiwyg editor using slate.js
I'm in a situation where I'm trying to find the first node with text.
This picture below shows what I'm talking about:
Slate.js find first text pic
In my picture, I'd want to find the node that contains "this is my title.", even if there's several empty lines before it.
Basically if I have a bunch of text written in the editor, how do I find the first text that's not an empty string?
Looking through the docs, I've found the filterDescendants and findDescendants functions which seem to do what I'm looking for.
However, I'm unclear how to use them.
I've tried something like this:
this.state.state.startBlock.findDescendant((d) => d.text !== "")
But this just returns null
The docs say that findDescendant will "Deeply find a descendant node by iterator", where iterator is a function, but there's no examples provided for what sort of function you'd pass here.
Does anyone have any ideas or examples?

Slate.js author here.
You'll like want to do something like:
state.document.getBlocks().find(block => block.text != '')
This will search through the leaf block nodes in the document (in this case your paragraphs, headers, etc.) and find the first one that isn't empty.
The Slate data model is built with Immutable.js, so reading up on how that library works is very helpful for using Slate. In this case getBlocks() returns an immutable List, which has a find method.
Hope that helps!

Related

How to get the text value of a CodeMirror-6 editor

I'm playing with CodeMirror to check if I can use it in our site to allow the user to write c# scripts. I can made a sample easily but I can't find any documentation nabout to get the text value of the editor to send through a form post.
JS Source:
import {StreamLanguage} from "#codemirror/language"
import {csharp} from "#codemirror/legacy-modes/mode/clike"
import {EditorView, basicSetup} from "codemirror"
let editor = new EditorView({
extensions: [basicSetup, StreamLanguage.define(csharp)],
parent: document.getElementById('_formengine_script')
})
index.html:
<!doctype html>
<meta charset=utf8>
<h1>CodeMirror!</h1>
<div id="_formengine_script"></div>
<script src="editor.bundle.js"></script>
I think that there must be various ways to solve it but I can't any of them. I've found a lot of information on CodeVersion 5, but I would prefer to use the latest version.
Ran into the same problem. The codemirror 6 documentation is odd. It contains lots of deep dives but lacks of the basics.
I ended up looking into the unit tests rather than the documentation. You find there a nice test in the history module, the test changes the document and then checks if the document contains the expected data.
Based on this, assuming editor is a reference to your EditorView, you endup with the following:
editor.state.doc.toString();
Update:
Just after writing this I stumbled upon https://codemirror.net/docs/migration/ just go there to the "Getting the Document and Selection" chapter. It contains the examples your searched for.
Editor allows to mark more than one selection range at once (example below)
You can get all of the selected ranges using this piece of code
editor.state.selection.ranges
Here an example how to get first selected text from all ranges.
let firstRange = editor.state.selection.ranges.at(0);
let selectedText = editor.state.doc.toString().substring(firstRange.from,firstRange.to)
console.log(selectedText); //output: 'ECT * FR'
The multimode selection can be disabled, but the way which you access the selected range stay the same.

If button is clicked and arrays match, run function in javascript

This is what I am trying to achieve: If a input image is clicked, and the input image matches word (referenced in array) run a previously ran function again.
I've messed around with the code but can not seem to figure out why it's not working.
I'm new enough to javascript so please excuse that lack of knowledge and terminology :P
You need to use array.indexOf(element)
Checkout this question
How do I check if an array includes an object in JavaScript?
Update: for your case yo better use array.some
randomwodrz.some(function(item){return item.word === 'word_to_match'})

Dashboard widget: getting version number from Info.plist

I'm writing a Dashboard widget in Dashcode, and on the back side, I've got a string for credits. I want to include the widget's version number in that string, but if possible, I want to programmatically grab it from the CFBundleVersion or CFBundleShortVersionString key in Info.plist to avoid having to change the number in multiple places if and when I update the widget.
Searches on Apple's developer documentation, Google and various forums have proven fruitless so far. What I'd like to know is whether there's a built-in way to do this that Apple included but forgot to mention (like var version = widget.version(); or something), or whether my script will have to pull in and parse the entire plist before plucking out the one value I actually want.
Thanks for any help you can provide!
I seem to have found the answer: use Dashcode's "data source" facility to read in Info.plist as an XML data source. From there, this blog post showed me how to traverse the plist's structure and get the correct string (in this case, the fifth <string> element in the file, corresponding to CFBundleShortVersionString.
The function I ended up with:
function getWidgetVersion() {
var dataSource = dashcode.getDataSource("infoPlist");
var version = dataSource.selection().valueForKey("dict").valueForKey("string")[4]; // This line and the previous could probably be combined for the sake of brevity
if (typeof(version) == 'string') {
document.getElementById("creditsLabel").innerHTML += version; //I'll change this to just pass the number on
}
}
Since the text of the creditsLabel div has already been started off with a localized string, I get a nice little label saying "Version 1.0".

Javascript xPath [#StoreName]?

I'm doing some research for a project that I have going on the uses the document.createTreeWalker and I'm looking at a script that uses quite a few xpath's, but I'm curious as to where these come from. Some are obvious and I have been able to find answers to online, such as [#AttributeName] and [#TagName], but what is [#StoreName], [#AttributeValue1], [#AttributeValue2]...these I have not been able to look up online.
Particularly, I'm looking at these lines and not understanding:
thisURL = window.document.location.href.toString();
if(thisURL.search("[#StoreName]") != -1) { //do something }
Perhaps I'm misunderstanding your question, but there's nothing functionally or syntactically different between [#AttributeName] and [#StoreName]. They're both predicates that are looking for elements with particular attributes. The first one is looking for AttributeName attributes, while the second is looking for StoreName attributes.
That said, the code you're showing isn't actually doing any XPath work. It's just looking at whether the URL contains the character sequence [#StoreName] using JavaScript's string search function, and doing something if it does.

Accessing a node-set in a JavaScript XPath query

I have a real simple question that I can't seem to find an answer to.
I want to compress two XPath statements (that are getting attribute values). I learned about the | operator, hearing how it returns node sets.
var getdata = xmldoc.evaluate
(
'/foo/bar[#world=\''+hello+'\']/child::*/attribute::name
|/foo/bar[#world=\''hello+'\']/child::*/attribute::id',
xmldoc, null, XPathResult.ANY_TYPE, null
);
To anyone wondering, no I do not format my evaluation strings that way ... though, I sort of like it now that I typed it out. Anyways, this is how I tested it out.
alert(getItemData.iterateNext().childNodes[0].nodeValue);
That works! But it only returns the first one. While writing this, I just tried .length and made a break through ... it's only counting one item. Was I deceived about the concept of |? How can I get a set and then go through them?
XML document, as requested.
<?xml version="1.0" encoding="ISO-8859-1"?>
<foo>
<bar world="hello" id="1">
<subbar name="item1" id="2">
</subbar>
</bar>
<bar world="bye" id="3">
<subbar name="item2" id="4">
</subbar>
</bar>
</foo>
Edit: I am currently using a function that grabs the element rather than the attribute, but I would really like to know the other way. Unless what I am doing is the best way.
If JQuery is an option, it might be worth your while to check out their XML traversal library. A quick search pulled up an article here. I wrote up a very rough example of what the logic may look like after you import the xml document, which is explained in the link.
var hello = "foo";
$('bar[world=' + hello + '] > subbar').each(function () {
// You'd want to save these values somewhere else, obviously.
$(this).getAttribute(name);
$(this).getAttribute(id);
});
The key here is the XPathResult type you use.
I have implemented a working sample for the same.
Please refer the code at http://jsbin.com/eneso3/5/edit
Basically you have to use Iterator as result type sot hat we can iterate through them to get the text. Refer Xpath reference mentioned on the working code sample page.
Well your usage of the "pipe" is correct (http://www.tizag.com/xmlTutorial/xpathbar.php) so the only code that I can see might be off is a missing + in the second xpath command, but that might be pseudo code, so I would only count this as a half answer. As for the best practice, in my opinion I would grab the subbar element then grab it's attributes out where you need them an optimization like the one you've suggested obfuscates what data is being referenced. Seems too much of a mico-optimization, but this is just an opinion. Maybe you have a long list of attributes and you really are saving parsing time.

Categories

Resources