I am trying to add a * if the label contains city, state, and zip. Also I only want it to happen if a * does not exist in the label already. Not sure if you can concatenate contains and not contains together. Also - I cannot edit the forms and some fields have * randomly put in. Here are two ways that failed for me.
Here is the Fiddle-https://jsfiddle.net/4o24kyLw/2/
Here is the jQuery
//$("label:contains('City'):not(:contains('*'),label:contains('Address'),label:contains('State'),label:contains('Zip')").prepend( "* " );
$("label:contains('City'):not(:contains('*'),label:contains('Address'),label:contains('State'),label:contains('Zip')").prepend( "* " );
Got the answer... but maybe I can take this in a different direction... can you simplify the contains. Similar to label:contains('City', 'State', 'etc...'):not(:contains('*')).prepend( "* " ) or maybe a way that works :]
This is the way it will be if it cannot be simplified - $("label:contains('City'):not(:contains('*')),label:contains('Mailing Address'):not(:contains('*')),label:contains('State'),label:contains('Postal Code'):not(:contains('*'))").prepend( "* " );
Rather than setting up a complicated query, you could check for the text within the prepend function itself:
$('label:not(:contains("*"))').prepend(function(_, txt) {
return 'AddressCityStateZip'.indexOf(txt)>-1 ? '* ' : '';
});
Fiddle
The indexOf function looks for text within a string, and it returns -1 if not found.
So if txt was 'City', 'AddressCityStateZip'.indexOf(txt) would return 7.
The conditional (ternary) operator returns an asterisk if there's a match – otherwise, it returns nothing.
Seems to work, you're just missing a )
$("label:contains('City'):not(:contains('*')),label:contains('Address'),label:contains('State'),label:contains('Zip')").prepend( "* " );
https://jsfiddle.net/5686hmnn/
The contains selector is pretty slow, and adding a whole set of them isn't going to help with speed or maintainability. You should use .filter() instead:
$("label").filter(function(idx){
var $(this).text() || '';
return (
(f.indexOf('City') > -1) ||
(f.indexOf('Address') > -1) ||
(f.indexOf('State') > -1) ||
(f.indexOf('Zip') > -1)
) &&
(f.indexOf('*') !== 0);
}).addClass('required');
Also, have you thought about using a css for the call-out instead? It offers several advantages. One of which being you don't really have to worry about modifying the text.
label.required:before { content: '* ' }
Also, you can style this right from the markup and not need to get javascript involved:
<label class="required">..</label>
But if you do need to use javascript it is much easier to find these labels:
$("label.required")
Related
Let's say I have the following text:
...at anyone who did not dress...
, where I need to find and replace "did not" with "did't" The task is simple until the text has styles and it becomes:
...at anyone who <span style='color: #ff0000;'>did</span>not dress...
If I just do
obj.innerText.replace("did not", "did't"),
then the style will not be saved, and
obj.innerHtml.replace("did not", "did't")
will not find
Is there an elegant solution?
UDP: there is a position in the text of the beginning and end of a phrase/word, as well as an index in case of repetition
const html = document.getElementsByTagName('p')[0].innerHTML;
const tags = html.match(/<\/?[^>]+(>|$)/g) || [];
const textTrue = html
.replace(/<\/?[^>]+(>|$)/g, '')
.replace('did not', "didn't");
var lastIndex = 0;
const tagsIndexs = tags.map((item) => {
lastIndex = html.indexOf(item, lastIndex);
return lastIndex;
});
const output = tags ? tags.reduce((result, tag, index) => {
return (
result.substr(0, tagsIndexs[index]) +
tag+
result.substr(tagsIndexs[index])
);
}, textTrue): textTrue;
document.getElementById('result').innerHTML = output;
<p>d<span style="color: #FF0000">id </span>not</p>
<div id='result'></div>
if 'not' is not styled(as shown in the example) the best approach I can think of is find all 'did' occurrences and then check if there is 'not' in the neighborhood. If yes remove the 'not' and replace the did with didn't. It is however performance intensive since you can not go for replace, but use indexOf in a while loop and manipulate the html string manually. Additionally if the styling varies(<span>,<b>,<i>..) it will be very difficult(if not impossible) to come with a valid criteria to evaluate the existence of 'not' in the neighborhood of the 'did'. The same approach can be used on 'not' instead of did, but again it really depends on the styling you need to preserve.
I'm new to AngularJS and trying to create a simple app that will allow me to upload files to my Laravel driven website. I want the form to show me the preview of what the uploaded item will look like. So I am using ng-model to achieve this and I have stumbled upon the following:
I have an input with some basic bootstrap stylings and I am using custom brackets for AngularJS templating (because as I mentioned, I am using Laravel with its blading system). And I need to remove spaces from the input (as I type it) and replace them with dashes:
<div class="form-group"><input type="text" plaeholder="Title" name="title" class="form-control" ng-model="gnTitle" /></div>
And then I have this:
<a ng-href="/art/[[gnTitle | spaceless]]" target="_blank">[[gnTitle | lowercase]]</a>
And my app.js looks like this:
var app = angular.module('neoperdition',[]);
app.config(function($interpolateProvider){
$interpolateProvider.startSymbol('[[').endSymbol(']]');
});
app.filter('spaceless',function(){
return function(input){
input.replace(' ','-');
}
});
I get the following error:
TypeError: Cannot read property 'replace' of undefined
I understand that I need to define the value before I filter it, but I'm not sure where to define it exactly. And also, if I define it, I don't want it to change my placeholder.
There are few things missing in your filter. First of all you need to return new string. Secondary, regular expression is not correct, you should use global modifier in order to replace all space characters. Finally you also need to check if the string is defined, because initially model value can be undefined, so .replace on undefined will throw error.
All together:
app.filter('spaceless',function() {
return function(input) {
if (input) {
return input.replace(/\s+/g, '-');
}
}
});
Demo: http://plnkr.co/edit/5Rd1SLjvNI18MDpSEP0a?p=preview
Bravi just try this filter
for eaxample {{X | replaceSpaceToDash}}
app.filter('replaceSpaceToDash', function(){
var replaceSpaceToDash= function( input ){
var words = input.split( ' ' );
for ( var i = 0, len = words.length; i < len; i++ )
words[i] = words[i].charAt( 0 ) + words[i].slice( 1 );
return words.join( '-' );
};
return replaceSpaceToDash;
});
First, you have to inject your filter in you module by adding it's name to the array :
var app = angular.module('neoperdition',['spaceless']);
Secondly, the function of the filter have to return something. The String.prototype.replace() return a new String. so you have to return it :
app.filter('spaceless',function(){
return function(input){
return input.replace(' ','-');
}
});
Edit: dfsq's answer being a lot more accurate than mine.
loopVar=1;
alert('#imgAvatar'+parseInt(loopVar)+1);
gives me #imgAvatar11
While
alert(parseInt(loopVar)+1);
gives me 2
How can I get #imgAvatar2 ?
Your loopVar is already an integer (notice you haven't put it in quotes, so it is integer). No need to do parseInt.
Use it:
loopVar=1;
alert('#imgAvatar'+(loopVar+1));
FIDDLE:
http://jsfiddle.net/15bucsy5/
It's because you're adding to the string #imgAvatar so the numbers will be converted to strings as well, and it's really read as "#imgAvatar" + "1" + "1".
Use parentheses to create a block where the numbers can be added up before they are added to the string
var loopVar = 1;
alert( '#imgAvatar' + ( (+loopVar) + 1 ) );
Whenever the addition operator is used with a string, all other values will be converted to strings as well
FIDDLE
Thats the trouble:
"foo" + 1 + 1 == "foo1"+1 == "foo11";
Thats the answer
alert( '#imgAvatar' + ( parseInt(loopVar) + 1) ) );
P.S. jsfiddle: https://jsfiddle.net/emtLfv9r/
If not worknig - show to us your html.
You need to add parenthesis () for priority to evaluate add loopVar first. If your variable contains numeric value then do not need to apply parseInt function.
loopVar = "1";
alert('#imgAvatar'+(parseInt(loopVar)+1));
OR
loopVar = 1;
alert('#imgAvatar'+ (loopVar+1) );
Demo
I'm looking to add to a string's value based on the output for multiple if statements but I don't seem to be having much success. I've declared comp_string="" at the beginning of the script then tried += so that for each condition that is true it adds a section on.
For the code example below if I submitted the value of www.facebook.com and www.twitter.com I would like comp_string to return 'fb=www.facebook.com&tw=www.twitter.com'
How would I go about concatenating/adding the string together and how do I add the & if more than one link is provided. I could add it to each string for any value thats not blank, but would an & on the end of the url with nothing following mess things up?
if (facebook_url != "") {
comp_string += "fb="+facebook_url;
}
if (twitter_url != "") {
comp_string += "tw="+twitter_url;
}
alert(comp_string);
A simple approach would be to add each string to an array, then join the array elements to produce the end result you are looking for.
var params = [];
if (facebook_url !== "") {
params.push("fb=" + facebook_url);
}
if (twitter_url !== "") {
params.push("tw=" + twitter_url);
}
alert(params.join("&"));
Reference
String(s) is dynamic
It is originated from onclick event when user clicks anywhere in dom
if string(s)'s first part that is:
"login<b>user</b>account"
is enclosed in some element like this :
"<div>login<b>user</b>account</div>",
then I can get it with this:
alert($(s).find('*').andSelf().not('b,i').not(':empty').first().html());
// result is : login<b>user</b>account
But how can i get the same result in this condition when it is not enclosed in any element .i.e. when it is not enclosed in any element?
I tried this below code which works fine when first part do not include any <b></b> but it only gives "login" when it does include these tags.
var s = $.trim('login<b>user</b> account<tbody> <tr> <td class="translated">Lorem ipsum dummy text</td></tr><tr><td class="translated">This is a new paragraph</td></tr><tr><td class="translated"><b>Email</b></td></tr><tr><td><i>This is yet another text</i></td> </tr></tbody>');
if(s.substring(0, s.indexOf('<')) != ''){
alert(s.substring(0, s.indexOf('<')));
}
Note:
Suggest a generic solution that is not specific for this above string only. It should work for both the cases when there is bold tags and when there ain't any.
So it's just a b or a i, heh?
A recursive function is always the way to go. And this time, it's probably the best way to go.
var s = function getEm(elem) {
var ret = ''
// TextNode? Great!
if (elem.nodeType === 3) {
ret += elem.nodeValue;
}
else if (elem.nodeType === 1 &&
(elem.nodeName === 'B' || elem.nodeName === 'I')) {
// Element? And it's a B or an I? Get his kids!
ret += getEm(elem.firstChild);
}
// Ain't nobody got time fo' empty stuff.
if (elem.nextSibling) {
ret += getEm(elem.nextSibling);
}
return ret;
}(elem);
Jsfiddle demonstrating this: http://jsfiddle.net/Ralt/TZKsP/
PS: Parsing HTML with regex or custom tokenizer is bad and shouldn't be done.
You're trying to retrieve all of the text up to the first element that's not a <b> or <i>, but this text could be wrapped in an element itself. This is SUPER tricky. I feel like there's a better way to implement whatever it is you're trying to accomplish, but here's a solution that works.
function initialText(s){
var test = s.match(/(<.+?>)?.*?<(?!(b|\/|i))/);
var match = test[0];
var prefixed_element = test[1];
// if the string was prefixed with an element tag
// remove it (ie '<div> blah blah blah')
if(prefixed_element) match = match.slice(prefixed_element.length);
// remove the matching < and return the string
return match.slice(0,-1);
}
You're lucky I found this problem interesting and challenging because, again, this is ridiculous.
You're welcome ;-)
Try this:
if (s.substring(0, s.indexOf('<')) != '') {
alert(s.substring(0, s.indexOf('<tbody>')));
}