I have make a custom filter in angular to first extract this pattern #[1:abc] from a string into into abc.Here is my code
Html :
<div class="mts mbs lg-feed-content-txt" hm-read-more hm-limit="200" hm-more-text="more" hm-less-text="less" hm-dots-class="toggle-dots-grey" hm-text="{{activity.post.text | mentionParser:activity.post}}" hm-link-class="toggle-readmore"></div>
Javasctipt:
.filter('mentionParser', function() {
return function(text, res) {
var text;
var regex = /[#[0-9]+[:]([a-z|A-Z ]+)]/g;
var idSeprator = /[0-9]+/g;
var displaySeprator = /([a-z|A-Z ]+)/g;
var pattern = text.match(regex);
var uidList = [];
var textCopy = text;
var mentions = [];
if (pattern != null) {
for (var j = 0; j < pattern.length; j++) {
var name ='<a>'+ res.mentionList[j].name +'</a>';
textCopy = textCopy.replace(pattern[j], name );
}
return textCopy;
} else {
return text;
}
}
});
What i want is that to make abc name linkable
I've created a JavaScript object to get the number of times a character repeats in a string:
function getFrequency(string) {
// var newValsArray =[];
var freq = {};
for (var i=0; i<string.length;i++) {
var character = string.charAt(i);
if (freq[character]) {
freq[character]++;
} else {
freq[character] = 1;
}
}
return freq;
}
Now, I'm trying to construct a new string composed of the keys & their properties (the letters) & numbers of times the letters repeat if the number (property) is more than one but I keep getting undefined and I don't know why:
function newString(freq){
var newValsArray = [];
for (var prop in freq) {
if (freq[prop]>1){
newValsArray.push(prop + freq[prop]);
}
else if (freq[prop] < 2){
newValsArray.push(prop);
}
}
return newValsArray;
}
I feel like my syntax is off or something... if anyone has any suggestions, I'd really appreciate it...
You aren't explicitly returning anything from newString(), so it will return undefined. It sounds like you want something like this:
return newValsArray.join('');
at the end of newString() to construct an actual string (instead of returning an array). With that change, newString(getFrequency("Hello there") will return 'He3l2o thr'.
function getFrequency(string) {
// var newValsArray =[];
var freq = {};
for (var i = 0; i < string.length; i++) {
var character = string.charAt(i);
if (freq[character]) {
freq[character] ++;
} else {
freq[character] = 1;
}
}
return freq;
}
function newString(freq) {
var newValsArray = [];
for (var prop in freq) {
if (freq[prop] > 1) {
newValsArray.push(prop + freq[prop]);
} else if (freq[prop] < 2) {
newValsArray.push(prop);
}
}
return newValsArray.join("");
}
var mystring = "Here are some letters to see if we have any freq matches and so on.";
var results = newString(getFrequency(mystring));
var elem = document.getElementById("results");
elem.innerHTML = results;
<div id="results"></div>
You are not returning anything from the newString function. Add return newString; as the last line of the newString function. Adding that line does result in something being returned, though I can't tell if it is what you expected.
var text = "asdfjhwqe fj asdj qwe hlsad f jasdfj asdf alhwe sajfdhsadfjhwejr";
var myFreq = getFrequency(text);
show(myFreq);
var myNewValsArray = newString(myFreq);
show(myNewValsArray);
function getFrequency(string) {
// var newValsArray =[];
var freq = {};
for (var i=0; i<string.length;i++) {
var character = string.charAt(i);
if (freq[character]) {
freq[character]++;
} else {
freq[character] = 1;
}
}
return freq;
}
function newString(freq){
var newValsArray = [];
for (var prop in freq) {
if (freq[prop]>1){
newValsArray.push(prop + freq[prop]);
}
else if (freq[prop] < 2){
newValsArray.push(prop);
}
}
return newValsArray; // ******** ADD THIS LINE
}
function show(msg) {
document.write("<pre>" + JSON.stringify(msg, null, 2) + "</pre>");
}
http://jsfiddle.net/84nv2dmL/
I'm trying to get these images of letters to display in order. I tried creating divs dynamically and filling them with the img, but that didn't work. How can I get these letters to display in order?
jsfiddle code:
function getQueryStringVar(name){
var qs = window.location.search.slice(1);
var props = qs.split("&");
for (var i=0 ; i < props.length;i++){
var pair = props[i].split("=");
if(pair[0] === name) {
return decodeURIComponent(pair[1]);
}
}
}
function getLetterImage(tag){
var flickerAPI = "https://www.flickr.com/services/feeds/photos_public.gne?jsoncallback=?";
return $.getJSON( flickerAPI, {
tags: tag,
tagmode: "all",
format: "json"
})
.then(function (flickrdata) {
//console.log(flickrdata);
var i = Math.floor(Math.random() * flickrdata.items.length);
var item = flickrdata.items[i];
var url = item.media.m;
return url;
});
}
$(document).ready(function() {
var name = getQueryStringVar("name") || "Derek";
var str = "letter,";
var searchtags = new Array()
for (var i = 0; i < name.length; i++) {
//console.log(str.concat(searchtags.charAt(i)));
searchtags[i] = str.concat(name.charAt(i));
}
for (var j = 0; j < name.length; j++){
var request = getLetterImage(searchtags[j]);
request.done(function(url) {
$("body").append("<img src="+ url + "></img>");
//var ele = document.createElement("div");
//ele.setAttribute("class", "img" + j--);
//document.body.appendChild(ele);
//$("<img src="+ url +"></img>").appendTo("img"+j);
});
}
//$("#img"+i).html("<img src="+ url + "></img>");
});
You basically need to keep track of the order that you are appending your images to the DOM, and make sure that they are in sync with the letters in the name. Created a fiddle with a fix. Comments are in line:
http://jsfiddle.net/84nv2dmL/2/
function getQueryStringVar(name) {
var qs = window.location.search.slice(1);
var props = qs.split("&");
for (var i = 0; i < props.length; i++) {
var pair = props[i].split("=");
if (pair[0] === name) {
return decodeURIComponent(pair[1]);
}
}
}
function getLetterImage(tag) {
var flickerAPI = "https://www.flickr.com/services/feeds/photos_public.gne?jsoncallback=?";
return $.getJSON(flickerAPI, {
tags: tag.char,
tagmode: "all",
format: "json"
})
.then(function(flickrdata) {
//console.log(flickrdata);
var i = Math.floor(Math.random() * flickrdata.items.length);
var item = flickrdata.items[i];
var url = item.media.m;
// return an object with url AND index
return {
ind: tag.ind,
img: url
};
});
}
$(document).ready(function() {
var name = getQueryStringVar("name") || "Derek";
var urls = new Array(name.length); // array or URLs, in correct order
var urlCounter = []; // keeps count or URLs received
var str = "letter,";
var searchtags = new Array();
for (var i = 0; i < name.length; i++) {
searchtags[i] = {
char: str.concat(name.charAt(i)),
ind: i
};
}
for (var j = 0; j < name.length; j++) {
var request = getLetterImage(searchtags[j]);
request.done(function(url) {
// when request is done, place image url in 'urls' array, in the correct order
urls[url.ind] = url.img;
// push object to the counter array, just to keep count
urlCounter.push(url);
// check if all image urls have been collected
checkComplete();
});
}
function checkComplete() {
// if the number of URLs received is equal
// to the number of characters in the name
// append the images from the ordered array
if (urlCounter.length == name.length) {
for (var k = 0; k < urls.length; k++) {
$("body").append("<img src=" + urls[k] + "></img>");
}
}
}
});
$("#div_id").append("<img src="+ url + "></img>");
Here div_id is the id you gave to the div.
Append adds img tag with source src to it.
Please give the html code too along with the script to help understand the problem better
I have some html page with text and need to output all inner HTML from tag b by alphabetical order in lower case. I'm just a begginer, so don't be strict.
My code is here (text is just for example): http://jsfiddle.net/pamjaranka/ebeptLzj/1/
Now I want to: 1) save upper case for inner HTML from tag abbr; 2) delete all similar element from the array (as MABs).
I was trying to find the way to split the array by tag, but all that I've done is:
for(var i=0; i<allbold.length; i++){
labels[i] = allbold[i].innerHTML;
}
var searchTerm = ['abbr'];
var abbr = [];
var keywordIndex;
$.each(labels, function(i) {
$.each(searchTerm, function(j) {
var rSearchTerm = new RegExp('\\b' + searchTerm[j] + '\\b','i');
if (labels[i].match(rSearchTerm)) {
keywordIndex = i;
for(var j=0; j<labels.length; j++){
abbr[i] = labels[i];
}
}
});
});
Vanilla JS solution (no library required, see jsFiddle):
var allbold = document.querySelectorAll("b"),
words = document.querySelector("#words"),
labels = {}, i, word, keys, label;
// first, collect all words in an object (this eliminates duplicates)
for(i = 0; i < allbold.length; i++) {
word = allbold[i].textContent.trim();
if (word === 'Labels:') continue;
labels[word.toLowerCase()] = word;
}
// then sort the object keys and output the words in original case
keys = Object.keys(labels).sort();
for(i = 0; i < keys.length; i++){
label = document.createTextNode("SPAN");
label.textContent = labels[keys[i]];
words.appendChild(label);
// add a comma if necessary
if (i < keys.length - 1) {
words.appendChild(document.createTextNode(", "));
}
}
with one helper:
String.prototype.trim = function () {
return this.replace(/^\s+|\s+$/g, "");
};
jQuery solution (see jsFiddle):
$(".content b").map(function () {
return $("<span>", {text: $.trim(this.textContent)})[0];
}).unique(function () {
return lCaseText(this);
}).sort(function (a, b) {
return lCaseText(a) < lCaseText(b) ? -1 : 1;
}).appendTo("#words");
with two helpers:
$.fn.extend({
unique: function (keyFunc) {
var keys = {};
return this.map(function () {
var key = keyFunc.apply(this);
if (!keys.hasOwnProperty(key)) {
keys[key] = true;
return this;
}
});
}
});
function lCaseText(element) {
return element.textContent.toLowerCase();
}
use the mapping element Is THIS FIDDLE for all upper case else this fiddle after your comment what you need
var maplabels = [];
for(var i=0; i<allbold.length; i++){
if (allbold[i].innerHTML != "Labels:") {
if(maplabels.indexOf(allbold[i].innerHTML) == -1){
maplabels.push(allbold[i].innerHTML);
labels.push('<i>' + allbold[i].innerHTML.toUpperCase() + '</i>');
}
}
}
I need to write a split function in JavaScript that splits a string into an array, on a comma...but the comma must not be enclosed in quotation marks (' and ").
Here are three examples and how the result (an array) should be:
"peanut, butter, jelly"
-> ["peanut", "butter", "jelly"]
"peanut, 'butter, bread', 'jelly'"
-> ["peanut", "butter, bread", "jelly"]
'peanut, "butter, bread", "jelly"'
-> ["peanut", 'butter, bread', "jelly"]
The reason I cannot use JavaScript's split method is because it also splits when the delimiter is enclosed in quotation marks.
How can I accomplish this, maybe with a regular expression ?
As regards the context, I will be using this to split the arguments passed from the third element of the third argument passed to the function you create when extending the jQuery's $.expr[':']. Normally, the name given to this parameter is called meta, which is an array that contains certain info about the filter.
Anyways, the third element of this array is a string which contains the parameters that are passed with the filter; and since the parameters in a string format, I need to be able to split them correctly for parsing.
What you are asking for is essentially a Javascript CSV parser. Do a Google search on "Javascript CSV Parser" and you'll get lots of hits, many with complete scripts. See also Javascript code to parse CSV data
Well, I already have a jackhammer of a solution written (general code written for something else), so just for kicks . . .
function Lexer () {
this.setIndex = false;
this.useNew = false;
for (var i = 0; i < arguments.length; ++i) {
var arg = arguments [i];
if (arg === Lexer.USE_NEW) {
this.useNew = true;
}
else if (arg === Lexer.SET_INDEX) {
this.setIndex = Lexer.DEFAULT_INDEX;
}
else if (arg instanceof Lexer.SET_INDEX) {
this.setIndex = arg.indexProp;
}
}
this.rules = [];
this.errorLexeme = null;
}
Lexer.NULL_LEXEME = {};
Lexer.ERROR_LEXEME = {
toString: function () {
return "[object Lexer.ERROR_LEXEME]";
}
};
Lexer.DEFAULT_INDEX = "index";
Lexer.USE_NEW = {};
Lexer.SET_INDEX = function (indexProp) {
if ( !(this instanceof arguments.callee)) {
return new arguments.callee.apply (this, arguments);
}
if (indexProp === undefined) {
indexProp = Lexer.DEFAULT_INDEX;
}
this.indexProp = indexProp;
};
(function () {
var New = (function () {
var fs = [];
return function () {
var f = fs [arguments.length];
if (f) {
return f.apply (this, arguments);
}
var argStrs = [];
for (var i = 0; i < arguments.length; ++i) {
argStrs.push ("a[" + i + "]");
}
f = new Function ("var a=arguments;return new this(" + argStrs.join () + ");");
if (arguments.length < 100) {
fs [arguments.length] = f;
}
return f.apply (this, arguments);
};
}) ();
var flagMap = [
["global", "g"]
, ["ignoreCase", "i"]
, ["multiline", "m"]
, ["sticky", "y"]
];
function getFlags (regex) {
var flags = "";
for (var i = 0; i < flagMap.length; ++i) {
if (regex [flagMap [i] [0]]) {
flags += flagMap [i] [1];
}
}
return flags;
}
function not (x) {
return function (y) {
return x !== y;
};
}
function Rule (regex, lexeme) {
if (!regex.global) {
var flags = "g" + getFlags (regex);
regex = new RegExp (regex.source, flags);
}
this.regex = regex;
this.lexeme = lexeme;
}
Lexer.prototype = {
constructor: Lexer
, addRule: function (regex, lexeme) {
var rule = new Rule (regex, lexeme);
this.rules.push (rule);
}
, setErrorLexeme: function (lexeme) {
this.errorLexeme = lexeme;
}
, runLexeme: function (lexeme, exec) {
if (typeof lexeme !== "function") {
return lexeme;
}
var args = exec.concat (exec.index, exec.input);
if (this.useNew) {
return New.apply (lexeme, args);
}
return lexeme.apply (null, args);
}
, lex: function (str) {
var index = 0;
var lexemes = [];
if (this.setIndex) {
lexemes.push = function () {
for (var i = 0; i < arguments.length; ++i) {
if (arguments [i]) {
arguments [i] [this.setIndex] = index;
}
}
return Array.prototype.push.apply (this, arguments);
};
}
while (index < str.length) {
var bestExec = null;
var bestRule = null;
for (var i = 0; i < this.rules.length; ++i) {
var rule = this.rules [i];
rule.regex.lastIndex = index;
var exec = rule.regex.exec (str);
if (exec) {
var doUpdate = !bestExec
|| (exec.index < bestExec.index)
|| (exec.index === bestExec.index && exec [0].length > bestExec [0].length)
;
if (doUpdate) {
bestExec = exec;
bestRule = rule;
}
}
}
if (!bestExec) {
if (this.errorLexeme) {
lexemes.push (this.errorLexeme);
return lexemes.filter (not (Lexer.NULL_LEXEME));
}
++index;
}
else {
if (this.errorLexeme && index !== bestExec.index) {
lexemes.push (this.errorLexeme);
}
var lexeme = this.runLexeme (bestRule.lexeme, bestExec);
lexemes.push (lexeme);
}
index = bestRule.regex.lastIndex;
}
return lexemes.filter (not (Lexer.NULL_LEXEME));
}
};
}) ();
if (!Array.prototype.filter) {
Array.prototype.filter = function (fun) {
var len = this.length >>> 0;
var res = [];
var thisp = arguments [1];
for (var i = 0; i < len; ++i) {
if (i in this) {
var val = this [i];
if (fun.call (thisp, val, i, this)) {
res.push (val);
}
}
}
return res;
};
}
Now to use the code for your problem:
function trim (str) {
str = str.replace (/^\s+/, "");
str = str.replace (/\s+$/, "");
return str;
}
var splitter = new Lexer ();
splitter.setErrorLexeme (Lexer.ERROR_LEXEME);
splitter.addRule (/[^,"]*"[^"]*"[^,"]*/g, trim);
splitter.addRule (/[^,']*'[^']*'[^,']*/g, trim);
splitter.addRule (/[^,"']+/g, trim);
splitter.addRule (/,/g, Lexer.NULL_LEXEME);
var strs = [
"peanut, butter, jelly"
, "peanut, 'butter, bread', 'jelly'"
, 'peanut, "butter, bread", "jelly"'
];
// NOTE: I'm lazy here, so I'm using Array.prototype.map,
// which isn't supported in all browsers.
var splitStrs = strs.map (function (str) {
return splitter.lex (str);
});
var str = 'text, foo, "haha, dude", bar';
var fragments = str.match(/[a-z]+|(['"]).*?\1/g);
Even better (supports escaped " or ' inside the strings):
var str = 'text_123 space, foo, "text, here\", dude", bar, \'one, two\', blob';
var fragments = str.match(/[^"', ][^"',]+[^"', ]|(["'])(?:[^\1\\\\]|\\\\.)*\1/g);
// Result:
0: text_123 space
1: foo
2: "text, here\", dude"
3: bar
4: 'one, two'
5: blob
If you can control the input to enforce that the string will be enclosed in double-quotes " and that all elements withing the string will be enclosed in single-quotes ', and that no element can CONTAIN a single-quote, then you can split on , '. If you CAN'T control the input, then using a regular expression to sort/filter/split the input would be about as useful as using a regular expression to match against xhtml (see: RegEx match open tags except XHTML self-contained tags)