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.
Related
I got a question while I parse html using JQuery.
Let me have a simple example for my question.
As you might definitely know, when I need to parse ...
<li class="info"> hello </li>
I get text by
$(".info").text()
my question is.. for given full html and token of text ,can I find query string ?
in case of above example, what I want to get is.
var queryStr = findQuery(html,"hello") // queryStr = '.info'
I know there might be more than one result and there would be various type of expression according to DOM hierarchy.
So.. generally... If some text (in this example, 'hello' ) is unique in the whole HTML, I might guess there must be a unique and shortest 'query' string which satisfies $(query).text() = "hello"
My question is.. If my guess is valid, How can I get unique (and if possible, shortest ) query string for each given unique text.
any hint will be appreciated, and thx for your help guys!
I create a little function that may help you:
function findQuery(str) {
$("body").children().each(function() {
if ( $.trim($(this).text()) == $.trim(str) ) {
alert("." + $(this).attr("class"))
}
});
}
See working demo
I am not sure what you're actually trying to achieve, but, based on your specific question, you could do the following.
var queryStr = findQuery($('<li class="info"> hello </li>'), "hello"); // queryStr = '.info'
// OR
var queryStr = findQuery('<li class="info"> hello </li>', "hello"); // queryStr = '.info'
alert (queryStr); // returns a string of class names without the DOT. You may add DOT(s) if need be.
function findQuery(html, str) {
var $html = html instanceof jQuery && html || $(html);
var content = $html.text();
if ( content.match( new RegExp(str, "gi") ) ) {
return $html.attr("class");
}
return "no matching string found!";
}
Hope this demo helps you!!
$(document).ready(function() {
var test = $("li:contains('hello')").attr('class');
alert(test);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="info">hello</li>
</ul>
Have used the jQuery attribute ":contains".
I'm new to KnockoutJS. I know how to define an observable that will be used to change the text of an element (or be updated from a text element), however, I want the data in my model to be actually a regular expression with read/write access. I want to set it using a textarea like:
<textarea data-bind="value: regex"></textarea>
And show it on the page using:
<span data-bind="text: regex"></span>
Now the initialization is working:
//inside the model
this.regex = ko.observable( /,/g );
And both the textarea and span get updated (because the native regular expression variable has a toString() function that works perfectly well showing a string representation of the regular expression). But when I change the regex in the textarea the span doesn't update. It seems like setting the observable is failing.
This is understandable because the value from textarea is just a text and in order to convert it to an actual regular expression, some code is needed. I have the code. Let's call it function str2regex() with a body similar to this:
//this is pseudo code and doesn't neccesarily work
function str2regex( str )
var r = str.match( "^\/(.+?)\/([mig])*$" );
if ( r ) {
if ( r[2] === null ) {
return new RegExp( r[1] );
} else {
return new RegExp( r[1], r[2] );
}
}
return null;
}
How can I set the value of type regular expression in my model using the text that is coming from the textarea?
You should transform your str2regex to computed observable like this:
// str2regex transformed to computed observable
self.regex = ko.computed(function(){
var m = self.regex_string().match(/^\/(.+)\/([mig])*$/);
return m ? new RegExp(m[1], m[2]) : null;
});
But you still should track your regex string editable in textarea (regex_string observable in my code).
Take a look: http://jsbin.com/ofehuj/2/edit
I got some long urls in my Json and I'm trying to figure out the best way to show only the domain using angular's filter or maybe just some javascript ?
http://www.example.com/page-with-a-long-long-long-OMG-so-long-name.html
to
www.example.com
thank you !
It's really easy in AngularJS to create your own filter:
app.filter( 'domain', function () {
return function ( input ) {
var matches,
output = "",
urls = /\w+:\/\/([\w|\.]+)/;
matches = urls.exec( input );
if ( matches !== null ) output = matches[1];
return output;
};
});
Which you can easily call in your view:
<span>{{ myUrl | domain }}</span>
Here's a Plunker: http://plnkr.co/edit/bVSv7n?builder&p=preview
This is a super-simple regex that you'll probably want to expand, but it works!
This angular filter will also work!
It is really cool and simple because it makes use of of the browsers built in URI parsing capability instead of relying on a regex.
angular.module('myCoolApp')
.filter('urlFilter', function ($document) {
return function (input) {
var parser = document.createElement('a');
parser.href = input;
return parser.hostname;
};
});
You can implement it in your view like this.
{{ myLongURL | urlFilter }}
If myLongURL is http://www.example.com/page-with-a-long-long-long-OMG-so-long-name.html, then it will show up as example.com after it passes through the filter. If you want the www. at the beginning you can just do this!
www.{{myLongURL | urlFilter}}
Use location.hostname to get the domain without an accruements.
http://fiddle.jshell.net/TUeJ7/
I created this filter
angular.module('App').filter( 'domainOfUrl',['$filter',function ($filter) {
return function ( input ) {
var urlParts = input.split('/');
return urlParts[2];
};
}]);
The above filter works like this:
input : https://www.amazon.in/b/ref=s9_acss_bw_***_x
output: www.amazon.in
use $filter if you want.
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>')));
}
A user of my HTML 5 application can enter his name in a form, and this name will be displayed elsewhere. More specifically, it will become the innerHTML of some HTML element.
The problem is that this can be exploited if one enters valid HTML markup in the form, i.e. some sort of HTML injection, if you will.
The user's name is only stored and displayed on the client side so in the end the user himself is the only one who is affected, but it's still sloppy.
Is there a way to escape a string before I put it in an elements innerHTML in Dojo? I guess that Dojo at one point did in fact have such a function (dojo.string.escape()) but it doesn't exist in version 1.7.
Thanks.
dojox.html.entities.encode(myString);
Dojo has the module dojox/html/entities for HTML escaping. Unfortunately, the official documentation still provides only pre-1.7, non-AMD example.
Here is an example how to use that module with AMD:
var str = "<strong>some text</strong>"
require(['dojox/html/entities'], function(entities) {
var escaped = entities.encode(str)
console.log(escaped)
})
Output:
<strong>some text</strong>
As of Dojo 1.10, the escape function is still part of the string module.
http://dojotoolkit.org/api/?qs=1.10/dojo/string
Here's how you can use it as a simple template system.
require([
'dojo/string'
], function(
string
){
var template = '<h1>${title}</h1>';
var message = {title: 'Hello World!<script>alert("Doing something naughty here...")</script>'}
var html = string.substitute(
template
, message
, string.escape
);
});
I tried to find out how other libraries implement this function and I stole the idea of the following from MooTools:
var property = (document.createElement('div').textContent == null) ? 'innerText': 'textContent';
elem[property] = "<" + "script" + ">" + "alert('a');" + "</" + "script" + ">";
So according to MooTools there is either the innerText or the textContent property which can escape HTML.
Check this example of dojo.replace:
require(["dojo/_base/lang"], function(lang){
function safeReplace(tmpl, dict){
// convert dict to a function, if needed
var fn = lang.isFunction(dict) ? dict : function(_, name){
return lang.getObject(name, false, dict);
};
// perform the substitution
return lang.replace(tmpl, function(_, name){
if(name.charAt(0) == '!'){
// no escaping
return fn(_, name.slice(1));
}
// escape
return fn(_, name).
replace(/&/g, "&").
replace(/</g, "<").
replace(/>/g, ">").
replace(/"/g, """);
});
}
// that is how we use it:
var output = safeReplace("<div>{0}</div",
["<script>alert('Let\' break stuff!');</script>"]
);
});
Source: http://dojotoolkit.org/reference-guide/1.7/dojo/replace.html#escaping-substitutions