I have a sentence stored in a variable.That sentence I need to extract into 4 parts depends on sentence which I have put into variables in my code,I can able to extract here and get into console but I am not getting the whole text of inside the bracket,only I am getting first words.Here is the code below.Can anyone please help me.
HTML
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="messages">
SCRIPT
$(document).ready(function() {
regex = /.+\(|\d. \w+/g;
maintext = "Welcome to project, are you a here(1. new user , 2. test user , 3. minor Accident or 4. Major Accident)";
matches = maintext.match(regex);
text_split0 = matches[0].slice(0, -1);
text_split1 = matches[1];
text_split2 = matches[2];
text_split3 = matches[3];
text_split4 = matches[4];
console.log(text_split0);
console.log(text_split1);
console.log(text_split2);
console.log(text_split3);
console.log(text_split4);
$(".messages").append('<li>'+text_split0+'</li><li>'+text_split1+'</li><li>'+text_split2+'</li><li>'+text_split3+'</li><li>'+text_split4+'</li>');
// $("li:contains('undefined')").remove()
});
function buildMessages(text) {
let messages = text.split(/\d\.\s/);
messages.shift();
messages.forEach((v)=>{
let msg = v.replace(/\,/,'').replace(/\sor\s/,'').trim();
$('.messages').append(`<li>${msg}</li>`);
// console.log(`<li>${msg}</li>`);
});
}
let sentenceToParse = "Welcome to project, are you a here(1. new user , 2. test user , 3. minor Accident or 4. Major Accident)";
buildMessages(sentenceToParse);
Use the split function on the String, keying on the digits (e.g. 1.), you will get the preface and each of the steps into an array.
Use the shift function on the Array removes the unneeded preface.
Use forEach to iterate over the values in the array, clean up the text.
Using replace to first remove commas, then remove or with spaces on either side.
Use trim to remove leading and training whitespace.
At this point, your array will have sanitized copy for use in your <li> elements.
If you're only concerned with working through a regex and not re-factoring, the easiest way may be to use an online regex tool where you provide a few different string samples. Look at https://www.regextester.com/
Ok, Try another approach, cause regex for this isn't the best way. Try this:
$(document).ready(function() {
// First part of sentence.
var mainText = "Welcome to project, are you a here(";
// Users array.
var USERS = ['new user', 'test user', 'minor Accident', 'Major Accident'];
var uSize = USERS.length;
// Construct string & user list dynamically.
for(var i = 0; i < uSize; i++) {
var li = $('<li/>').text(USERS[i]);
if(i === uSize - 1)
mainText += (i+1) + ". " + USERS[i] + ")";
else if(i === uSize - 2)
mainText += (i+1) + ". " + USERS[i] + " or ";
else
mainText += (i+1) + ". " + USERS[i] + " , ";
$(".messages").append(li);
}
console.log(mainText); // You will have you complete sentence.
}
Why that way is better? Simple, you can add or remove users inside the user array. String together with your user list will be updated automatically. I hope that help you.
First let me apologize for my ignorance when it comes to js.
Is it possible to extract a time from text? For example, i'd like to extract the time from the following text "Results phoned by _ to _ at 2018/04/12 01:31:33. Results confirmed. Read back."
Is this even possible to accomplish this? The software that I use allows for both js and BIRT coding. Any help would be appreciated.
var str = dataSetRow["Comment - Result"];
var time = str.match(/([0-1]\d|2[0-3]):([0-5]\d):([0-5]\d)/g);
time;
Outputs to "Ljava.lang.Object;#bd6334" and i have no idea how to fix it.
I get the "Ljava.lang.Object;#" error for every row of my table with different characters after the #
If I change the code to:
var str = dataSetRow["Comment - Result"];
var time = str.match(/\d{2}:\d{2}:\d{2}/g);
if (time.length>0) time [0];
else "";
I get the desired result but it will only display 1 row of a table with significantly more rows. Am I missing something?
Managed to get it working with some help from our system's manufacturer:
var str = dataSetRow["Comment - Result"];
var time = null;
if (str != null) time = str.match(/\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}/);
var output = "";
if (time != null) {
for (var i = 0; i < time.length; ++i) {
if (i > 0) output += "\n"; // this adds a line break in a computed column expression
output += time[i];
}
}
output;
This is about a Chrome Extension.
Suppose a user select any text on a page, then clicks a button to save it. Via window.getSelection() I can get that text without the underlying html markup.
I store that text. For demo purposes, let's say the text is:
"John was much more likely to buy if he knew the price beforehand"
The next time the user visits the page, I want to find that text on the page. The issue is, the html for that text is actually:
<b>John was much more likely to buy if he knew the price <span class="italic">beforehand</span></b>
The second issue is that this system needs to work even if the selection is dirty, i.e. it starts/ends mid DOM node.
What I've build is bit of a fat solution, so I am curious how I can make it more efficient and/or smaller. This is the whole thing:
text.split("").map(function(el, i, arr){
if(specials.includes(el)){
return "\\"+el;
}
return el;
})
.join("(?:\\s*<[^>]+>\\s*)*\\s*");
where text is the saved text and specials is
var specials = [
'/', '.', '*', '+', '?', '|',
'(', ')', '[', ']', '{', '}', '\\'
];
The process is:
Split text into single characters
For each character, check if it's a special char and if so, prepend it with \
Join all letters together with regEx that check if there's any whitespace or html tags inbetween
My question is, can it be done in a better way? I get the "bruteforcing" feeling with this solution and I don't know if it would actually cause lag on larger sites/selection texts.
Plus, it doesn't work for SPAs where text may update a bit after the DOM is ready.
Thank you for any input.
EDIT:
So initially I was using mark.js, which doesn't handle this at all, but not 12 hours after I posted this question the maintainer release v8.0.0 that uses NodeList and handles my use case. The feature is "acrossElements", located here.
create a Range object
set it so that it spans the entire document from start to end
check if the string of interest is in its toString()
clone range twice
apply binary search by moving the start/end points of the subranges into roughly their midpoint. this can be approximated by finding the first descendant with > 1 child nodes and then splitting the child list
goto 3
this should roughly take n log m steps where n is the document text length and m the number of nodes.
Build the entire text representation of the document manually from each node with nodeType of Node.TEXT_NODE, saving the node reference and its text's start/end positions relative to the overall string in an array. Do it just once as DOM is slow, and you might want to search for multiple strings. Otherwise the other answer might be much faster (without actual benchmarks it's a moot point).
Apply HTML whitespace coalescing rules.
Otherwise you'll end up with huge spans of spaces and newline characters.
For example, Range.toString() doesn't strip them, meaning you'd have to convert your string to a RegExp with [\s\n\r]+ instead of spaces and all other special characters like {}()[]|^$*.?+ escaped.
Anyway, it'd be wise to use the converted RegExp on document.body.textContent before proceeding (easy to implement, many examples on the net, thus not included below).
A simplified implementation for plain-string search follows.
function TextMap(baseElement) {
this.baseElement = baseElement || document.body;
var textArray = [], textNodes = [], textLen = 0, collapseSpace = true;
var walker = document.createTreeWalker(this.baseElement, NodeFilter.SHOW_TEXT);
while (walker.nextNode()) {
var node = walker.currentNode;
var nodeText = node.textContent;
var parentName = node.parentNode.localName;
if (parentName==='noscript' || parentName==='script' || parentName==='style') {
continue;
}
if (parentName==='textarea' || parentName==='pre') {
nodeText = nodeText.replace(/^(\r\n|[\r\n])/, '');
collapseSpace = false;
} else {
nodeText = nodeText.replace(/^[\s\r\n]+/, collapseSpace ? '' : ' ')
.replace(/[\s\r\n]+$/, ' ');
collapseSpace = nodeText.endsWith(' ');
}
if (nodeText) {
var len = nodeText.length;
textArray.push(nodeText);
textNodes.push({
node: node,
start: textLen,
end: textLen + len - 1,
});
textLen += len;
}
}
this.text = textArray.join('');
this.nodeMap = textNodes;
}
TextMap.prototype.indexOf = function(str) {
var pos = this.text.indexOf(str);
if (pos < 0) {
return [];
}
var index1 = this.bisectLeft(pos);
var index2 = this.bisectRight(pos + str.length - 1, index1);
return this.nodeMap.slice(index1, index2 + 1)
.map(function(info) { return info.node });
}
TextMap.prototype.bisect =
TextMap.prototype.bisectLeft = function(pos) {
var a = 0, b = this.nodeMap.length - 1;
while (a < b - 1) {
var c = (a + b) / 2 |0;
if (this.nodeMap[c].start > pos) {
b = c;
} else {
a = c;
}
}
return this.nodeMap[b].start > pos ? a : b;
}
TextMap.prototype.bisectRight = function(pos, startIndex) {
var a = startIndex |0, b = this.nodeMap.length - 1;
while (a < b - 1) {
var c = (a + b) / 2 |0;
if (this.nodeMap[c].end > pos) {
b = c;
} else {
a = c;
}
}
return this.nodeMap[a].end >= pos ? a : b;
}
Usage:
var textNodes = new TextMap().indexOf('<span class="italic">');
When executed on this question's page:
[text, text, text, text, text, text]
Those are text nodes, so to access corresponding DOM elements use the standard .parentNode:
var textElements = textNodes.map(function(n) { return n.parentNode });
Array[6]
0: span.tag
1: span.pln
2: span.atn
3: span.pun
4: span.atv
5: span.tag
I have the code below working well. It searches my xml file for all the "outcome_text" nodes of a particular branch (the 'str' branch), then writes the text to a table. Problem is, I would really like to get the value of the parent nodes attribute as well (the overall id value). That way my table row would be two columns: OVerall ID and Outcome.
I can do it no problem in VB/asp xpath, but trying to make a client side version for mobile.
here is a snippet of the xml:
<curriculum>
<strand id="Dance">
<strand_text>Dance</strand_text>
<overalls>
<overall id="A1">
<overall_text>Creating and Presenting: apply the creative process (see pages 19-22) to the composition of simple dance phrases, using the elements of dance to communicate feelings and ideas</overall_text>
<specifics>
<specific></specific>
</specifics>
</overall>
<overall id="A2">
<overall_text>Reflecting, Responding, and Analysing: apply the critical analysis process (see pages 23-28) to communicate their feelings, ideas, and understandings in response to a variety of dance pieces and experiences</overall_text>
<specifics>
<specific></specific>
</specifics>
</overall>
</overalls>
</strand>
<strand id="visual"> . . . </strand>
</curriculum>
and here is the code: (ignore the IE bits--it will be on Android and IOS only)
<script>
function popout() {
var gr = gradedd.options[gradedd.selectedIndex].value
var sb = subdd.options[subdd.selectedIndex].value
var str = stranddd.options[stranddd.selectedIndex].value
xml = loadXMLDoc("resources/ont/grade_" + gr + "_" + sb + ".xml");
path = "/curriculum/strand[#id='" + str + "']/overalls/overall/overall_text"
// code for IE
if (window.ActiveXObject) {
var nodes = xml.selectNodes(path);
for (i = 0; i < nodes.length; i++) {
// ddlist[0] = nodes[i].childNodes[0].nodeValue; ignore
// dropdown[dropdown.length] = new Option(ddlist[i], ddlist[i]); ignore
}
}
// code for Mozilla, Firefox, Opera, etc.
else if (document.implementation && document.implementation.createDocument) {
var nodes = xml.evaluate(path, xml, null, XPathResult.ANY_TYPE, null);
var result = nodes.iterateNext();
var txt = "<table border='1'><tr><th>Strand</th><th>OVERALL</th></tr>";
while (result) {
ind = str; // but would like the value of outcome node attribute
var over = result.childNodes[0].nodeValue
txt = txt + "<tr><td>" + ind + "</td><td>" + over + "</td></tr>"
result = nodes.iterateNext();
}
}
txt = txt + "</table>"
document.getElementById('outtable').innerHTML = txt;
}
Seems to me something like:
ind = result.parentNode.getAttribute("id")
should work.
I want to display YouTube videos on my website, but I need to be able to add a unique id for each video that's going to be shared by users. So I put this together, and I have run into a little problem. I am trying to get the JavaScript to add a random string for the div id, but it's not working, showing the string:
<script type='text/javascript' src='jwplayer.js'></script>
<script type='text/javascript'>
function randomString(length) {
var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'.split('');
if (! length) {
length = Math.floor(Math.random() * chars.length);
}
var str = '';
for (var i = 0; i < length; i++) {
str += chars[Math.floor(Math.random() * chars.length)];
}
return str;
}
var div = randomString(8);
</script>
<div id='div()'>This text will be replaced</div>
<script type='text/javascript'>
jwplayer('div()').setup({
'flashplayer': 'player.swf',
'file': 'http://www.youtube.com/watch?v=4AX0bi9GXXY',
'controlbar': 'bottom',
'width': '470',
'height': '320'
});
</script>
I really like this function:
function guidGenerator() {
var S4 = function() {
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
};
return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
}
From Create GUID / UUID in JavaScript?
2018 edit: I think this answer has some interesting info, but for any practical applications you should use Joe's answer instead.
A simple way to create a unique ID in JavaScript is to use the Date object:
var uniqid = Date.now();
That gives you the total milliseconds elapsed since January 1st 1970, which is a unique value every time you call that.
The problem with that value now is that you cannot use it as an element's ID, since in HTML, IDs need to start with an alphabetical character. There is also the problem that two users doing an action at the exact same time might result in the same ID. We could lessen the probability of that, and fix our alphabetical character problem, by appending a random letter before the numerical part of the ID.
var randLetter = String.fromCharCode(65 + Math.floor(Math.random() * 26));
var uniqid = randLetter + Date.now();
This still has a chance, however slim, of colliding though. Your best bet for a unique id is to keep a running count, increment it every time, and do all that in a single place, ie, on the server.
Here is the reusable function to generate the random IDs :
function revisedRandId() {
return Math.random().toString(36).replace(/[^a-z]+/g, '').substr(2, 10);
}
// It will not start with the any number digit so it will be supported by CSS3
I think some folks here haven't really focused on your particular question. It looks like the problem you have is in putting the random number in the page and hooking the player up to it. There are a number of ways to do that. The simplest is with a small change to your existing code like this to document.write() the result into the page. I wouldn't normally recommend document.write(), but since your code is already inline and what you were trying do already was to put the div inline, this is the simplest way to do that. At the point where you have the random number, you just use this to put it and the div into the page:
var randomId = "x" + randomString(8);
document.write('<div id="' + randomId + '">This text will be replaced</div>');
and then, you refer to that in the jwplayer set up code like this:
jwplayer(randomId).setup({
And the whole block of code would look like this:
<script type='text/javascript' src='jwplayer.js'></script>
<script type='text/javascript'>
function randomString(length) {
var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghiklmnopqrstuvwxyz'.split('');
if (! length) {
length = Math.floor(Math.random() * chars.length);
}
var str = '';
for (var i = 0; i < length; i++) {
str += chars[Math.floor(Math.random() * chars.length)];
}
return str;
}
var randomId = "x" + randomString(8);
document.write('<div id="' + randomId + '">This text will be replaced</div>');
jwplayer(randomId).setup({
'flashplayer': 'player.swf',
'file': 'http://www.youtube.com/watch?v=4AX0bi9GXXY',
'controlbar': 'bottom',
'width': '470',
'height': '320'
});
</script>
Another way to do it
I might add here at the end that generating a truly random number just to create a unique div ID is way overkill. You don't need a random number. You just need an ID that won't otherwise exist in the page. Frameworks like YUI have such a function and all they do is have a global variable that gets incremented each time the function is called and then combine that with a unique base string. It can look something like this:
var generateID = (function() {
var globalIdCounter = 0;
return function(baseStr) {
return(baseStr + globalIdCounter++);
}
})();
And, then in practical use, you would do something like this:
var randomId = generateID("myMovieContainer"); // "myMovieContainer1"
document.write('<div id="' + randomId + '">This text will be replaced</div>');
jwplayer(randomId).setup({
i like this simple one:
function randstr(prefix)
{
return Math.random().toString(36).replace('0.',prefix || '');
}
since id should (though not must) start with a letter, i'd use it like this:
let div_id = randstr('youtube_div_');
some example values:
youtube_div_4vvbgs01076
youtube_div_1rofi36hslx
youtube_div_i62wtpptnpo
youtube_div_rl4fc05xahs
youtube_div_jb9bu85go7
youtube_div_etmk8u7a3r9
youtube_div_7jrzty7x4ft
youtube_div_f41t3hxrxy
youtube_div_8822fmp5sc8
youtube_div_bv3a3flv425
I also needed a random id, I went with using base64 encoding:
btoa(Math.random()).substring(0,12)
Pick however many characters you want, the result is usually at least 24 characters.
Based on HTML 4, the id should start from letter:
ID and NAME tokens must begin with a letter ([A-Za-z]) and may be followed by any number of letters, digits ([0-9]), hyphens ("-"), underscores ("_"), colons (":"), and periods (".").
So, one of the solutions could be (alphanumeric):
var length = 9;
var prefix = 'my-awesome-prefix-'; // To be 100% sure id starts with letter
// Convert it to base 36 (numbers + letters), and grab the first 9 characters
// after the decimal.
var id = prefix + Math.random().toString(36).substr(2, length);
Another solution - generate string with letters only:
var length = 9;
var id = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, length);
Or you could use Cripto since it's already built in(except in IE11, I swear these guys havent updated in years!)
https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues#Examples
var id = new Uint32Array(10);
window.crypto.getRandomValues(id);
I also found this:
https://gist.github.com/6174/6062387#gistcomment-3255605
let length = 32;
let id = crypto.randomBytes(length).toString("base64");
There's a lot of ways to do this, but for most people, there's no reason to reinvent the wheel :)
A edited version of #jfriend000 version:
/**
* Generates a random string
*
* #param int length_
* #return string
*/
function randomString(length_) {
var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghiklmnopqrstuvwxyz'.split('');
if (typeof length_ !== "number") {
length_ = Math.floor(Math.random() * chars.length_);
}
var str = '';
for (var i = 0; i < length_; i++) {
str += chars[Math.floor(Math.random() * chars.length)];
}
return str;
}
For generating random ids, you can also use the standard crypto API with its randomUUID() function which is available in node.js (>=v16.7.0) and all relevant browsers except Safari:
const uuid = crypto.randomUUID()
console.log(uuid)
// prints e.g. "7f3f4512-fcf9-45fe-b726-512bba403426"
I would suggest that you start with some sort of placeholder, you may have this already, but its somewhere to append the div.
<div id="placeholder"></div>
Now, the idea is to dynamically create a new div, with your random id:
var rndId = randomString(8);
var div = document.createElement('div');
div.id = rndId
div.innerHTML = "Whatever you want the content of your div to be";
this can be apended to your placeholder as follows:
document.getElementById('placeholder').appendChild(div);
You can then use that in your jwplayer code:
jwplayer(rndId).setup(...);
Live example: http://jsfiddle.net/pNYZp/
Sidenote: Im pretty sure id's must start with an alpha character (ie, no numbers) - you might want to change your implementation of randomstring to enforce this rule. (ref)
May I an share an intuitive way to generate a randomID ?
const getRandomID = (length: number) => {
let text = '';
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < length; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
Here is an easy one liner:
const generateUniqueID = (idLength) => [...Array(idLength).keys()].map((elem)=>Math.random().toString(36).substr(2, 1)).join("")
Where all you do is enter the idLength and it will return a unique id of that length.
generateUniqueID(23)
>>>'s3y9uebzuo73ih79g0s9p2q' // Id of length 23
First. Assign an id to your div. Like this:
<div id="uniqueid">This text will be replaced</div>
After that, add inside your <script> tag following code:
Document.getElementById("uniqueid").id = randomString(8);
window.btoa(String.fromCharCode(...window.crypto.getRandomValues(new Uint8Array(5))))
Using characters except ASCII letters, digits, '_', '-' and '.' may cause compatibility problems, as they weren't allowed in HTML 4. Though this restriction has been lifted in HTML5, an ID should start with a letter for compatibility.
function id(prefix = '', length = 7) {
let result = prefix;
for(let i = 0; i < length; i++) {
const random = Math.random();
result += String.fromCharCode(Math.floor(random * 26) + (random < .5 ? 65 : 97));
}
return result;
}
a random number between 0 and 25 is generated then added to either 65 or 97. When added to 65 it will give you an ascii code for a capital letter and when added to 97, an ascii code for a small letter.
Just use built-int crypto.randomUUID() which is supportted by all major browsers:
let uuid = crypto.randomUUID();
console.log(uuid);