I have the currency "Rs." occurring on multiple places on my site. I want to wrap every occurrence of the text with <span class="WebRupee">. But if it is already wrapped with <span class="WebRupee"> it should be ignored.
I cannot use $('*:contains("Rs.")').wrap("<span class=\"WebRupee\"); because this wraps the html around the node that contains Rs. but not around the text alone. And for the same reason I cannot use .wrapInner();
Again any help will be greatly appreciated!
EDIT : the javascript provided on the webrupee site doesn't work on my site(no clue why). So that's out of the question as a solution. And hence I thought of writing a custom javascript. Just don't know how I could approach this.
EDIT(2): thinking out loud - hmm is there a way to add html at the indexOf("Rs.") ..or a simmilar approach
First, what you are trying to do is a dirty hack.
You should fix it in the source, whatever it is (for example PHP backend, Ruby backend, plain HTML, etc...).
See this example working at http://jsfiddle.net/8jXLw/
I did many assumptions and simplifications, your Regular Expressions should be more complete.
var spanit = function(item) {
var $item = jQuery(item);
var regexp = /\d+ Rs\./;
var text = $item.text();
if (!regexp.test(text)) {
return;
}
if ($item.has(".WebRupee").length) {
return;
}
var new_text = text.replace(" Rs."," <span class='WebRupee'>Rs.</span>");
$item.html(new_text);
};
jQuery(function() {
$("p.test").each(function() {
spanit(this);
});
});
Use http://cdn.webrupee.com/js file. it is working fine. i had used for one website.
If you want download and customize little..
thanks..
very inefficient solution
var replaced = $("body").html().replace('Rs.','<span class="WebRupee">Rs.</span>');
$('body').html(replaced);
var replaced = $("body").html().replace('<span class="WebRupee"><span class="WebRupee">Rs.</span></span>','<span class="WebRupee">Rs.</span>');
$('body').html(replaced);
Related
I'm creating a project in Adobe Experience Manager and have run into problems in the implementation of my language switching component. The component is supposed allow the user to click on a link and have the language of the page change. For example, if they are on the English page /content/myproject/en/home.html and they click it, they are supposed to end up on /content/myproject/fr_ca/home.html.
As part of getting it up and running, I was trying to concatenate currentPage.path and "/profile.html" so that I could at least get the component to register some change to the string in the tag.
From the English home.html page, currentPage.path produces the string "/content/myproject/en/home". Concatenating it with /profile.html should produce the string "/content/myproject/en/home/profile.html" which it does if I use Sightly to do something like <p>${langinfo.goToPage}</p>.
However, if I try this: the component will show a blank anchor tag. It will also blank anything I've written in between the two anchor tags.
So far I've tried returning a string I've written out by hand "/content/myproject/en/home/profile.html" as the goToPage value and it works in the anchor tag. Also, if I only return currentPage.path it works. It refuses to work like this if I try to concatenate but it will work like this: <a>It works here!.
The best I can figure at this point is that currentPage.path is a Java String object that is being accessed by JavaScript and there are problems when JS tries to type it to a JavaScript string with +. It also doesn't work if I try to cast the statement as a string with either String(goToPage) or goToPage.toString(). It doesn't seem to matter when I cast it as a string. One blog I looked at seemed to hint that this was a problem with Rhino and that I should do a .toString() after the initial concatenation. That didn't work. Another post on stackOverflow seemed to point out that it could be a problem trying to concatenate a Java String object in JavaScript and pointed out that this should be taken into account but didn't go into how to deal with the issue.
I appending to a string isn't the intended end functionality of my component, but if I can't modify the string by concatenating, seems like I can hardly do a search and replace to change /en/ to /fr-ca/. If anyone has a more elegant solution to my problem than what I'm attempting, that would be appreciated as much as a fix for what I'm working on.
I've pasted my code here (as suggested) and posted screenshots of my code to help.
Javascript:
use(function() {
var pageLang = currentPage.properties.get("jcr:language", "en");
var otherLangText;
var currPage = currentPage.name;
var currPagePath = currentPage.path;
var goPage;
if (pageLang == "fr_ca") {
otherLangText = "English";
goPage = "/content/myproject/en/index/home.html";
} else {
otherLangText = "Français";
goPage = "/content/myproject/fr-ca/home/home.html";
};
return {
otherLanguage: otherLangText,
goToPage: goPage
}
})
HTML:
<nav data-sly-use.langinfo="langcontact.js">
<ul class="lang-list-container">
<li class="lang-list-item">${langinfo.otherLanguage}</li>
<li class="lang-list-item">Contact</li>
</ul>
</nav>
I'm pretty stumped here. What am I doing wrong?
The line <li class="lang-list-item">${langinfo.otherLanguage}</li>
should actually be -
<li class="lang-list-item">${langinfo.otherLanguage}</li>
What you are trying to do is pass an object to object which will not work, in case you want to pass the extension to be used in JS you need to do that in the USE call. Refer to the samples in this blog.
Update -
You code works fine for me as long as the link is valid.
use(function() {
var pageLang = currentPage.properties.get("jcr:language", "en");
var otherLangText;
var currPage = currentPage.name;
var currPagePath = currentPage.path;
var goPage;
if (pageLang == "fr_ca") {
otherLangText = "English";
goPage = currPagePath+"/profile.html";
} else {
otherLangText = "Français";
goPage = currPagePath+"/profile.html";
};
return {
otherLanguage: otherLangText,
goToPage: goPage
}
})
The only possible reason you are getting empty href is because your link is not valid and thus linkchecker is removing it. If you check on author instance you will see broken link symbol along with your link text.
Ideally you should fix the logic so that proper valid link is generated. On development you could disable the linkchecker and/orlink transformer to let all links work (even invalid ones | not recommended). The two services can be checked in http://localhost:4502/system/console/configMgr by searching for - Day CQ Link Checker Service and Day CQ Link Checker Transformer
I am trying to create a very simplistic XSS detection system for a system I am currently developing. The system as it stands, allows users to submit posts with javascript embedded within the message. Here is what I currently have:-
var checkFor = "<script>";
alert(checkFor.indexOf("<script>") !== -1);
This doesn't really work that well at all. I need to write code that incorporates an array which contains the terms I am searching for [e.g - "<script>","</script>","alert("]
Any suggestions as to how this could be achieved using JavaScript/jQuery.
Thanks for checking this out. Many thanks :)
Replacing characters is a very fragile way to avoid XSS. (There are dozens of ways to get < in without typing the character -- like < Instead, HTML-encode your data. I use these functions:
var encode = function (data) {
var result = data;
if (data) {
result = $("<div />").html(data).text();
}
};
var decode = function (data) {
var result = data;
if (data) {
result = $("<div />").text(data).html();
}
};
As Explosion Pills said, if you're looking for cross–site exploits, you're probably best to either find one that's already been written or someone who can write one for you.
Anyway, to answer the question, regular expressions are not appropriate for parsing markup. If you have an HTML parser (client side is easy, server a little more difficult) you could insert the text as the innerHTML of an new element, then see if there are any child elements:
function mightBeMarkup(s) {
var d = document.createElement('div');
d.innerHTML = s;
return !!(d.getElementsByTagName('*').length);
}
Of course there still might be markup in the text, just that it's invalid so doesn't create elements. But combined with some other text, it might be valid markup.
The most effective way to prevent xss attacks is by replacing all <, > and & characters with
<, >, and &.
There is a javascript library from OWASP. I haven't worked with it yet so can't tell you anything about the quality. Here is the link: https://www.owasp.org/index.php/ESAPI_JavaScript_Readme
I'm developing a contentEditable region on my website, where users will be able to type messages to each other.
<div contentEditable="true" class="smartText">User types here...</div>
The thing is, we will have smart text inside, meaning that if a user type #usersame inside this div, the #username should be highlighted in blue if the username exist and green if he doesn't exist. And of course all of this should happen as the user types...
I have no idea where to start, right now I have this:
$("body").on("keyup",".smartText",function(){
var $this = $(this),
value = $this.html(),
regex = /[^>]#\S+[^ ]/gim;
value = value.replace(regex,"<span style='color:red'>$&</span>");
$this.html(value);
});
But the text keeps jumping (as well as the caret position) and doesn't feel like the right direction. I guess it's a little similar to JSFiddle which colors code as it finds it.
I basically want the same thing as Twitter has.
Here is a JSFiddle to play around with: http://jsfiddle.net/denislexic/bhu9N/4/
Thanks in advance for your help.
I liked this problem and I worked very hard to solve. I believe I have finally succeeded (with a little assistance).
= UPDATED =
Piece of Code:
[...]
// formatText
formatText: function (el) {
var savedSel = helper.saveSelection(el);
el.innerHTML = el.innerHTML.replace(/<span[\s\S]*?>([\s\S]*?)<\/span>/g,"$1");
el.innerHTML = el.innerHTML.replace(/(#[^\s<\.]+)/g, helper.highlight);
// Restore the original selection
helper.restoreSelection(el, savedSel);
}
[...]
// point
keyup: function(e){
// format if key is valid
if(helper.keyIsAvailable(e)){
helper.formatText($this[0]);
}
// delete blank html elements
if(helper.keyIsDelete && $this.text()=="") {
$this.html("");
}
}
Screenshot:
JSFiddle here: http://jsfiddle.net/hayatbiralem/9Z3Rg/11/
Needed External Resources:
http://dl.dropboxusercontent.com/u/14243582/jscalc/js/rangy-core.js
http://dl.dropboxusercontent.com/u/14243582/jscalc/js/rangy-selectionsaverestore.js
Helper Question (thanks): replace innerHTML in contenteditable div
Regex Test Tool (thanks): http://www.pagecolumn.com/tool/regtest.htm
Keep in mind that the HTML markup typed by the user could be quite surprising, e.g: <span>#use</span><span>rname</span>, which still looks like #username to the user.
To avoid the crazy caret behavior (and some other nasty side effects) inside a contentEditable element, you should use W3C DOM API and walk the DOM tree each time there is a change in HTML (you can sniff the change by polling body.innerHTML upon a timer).
I've recently answered a similar question for CKEditor and described the algorithm of how to build a text-to-node map of the DOM, for finding a text match. The CKEditor DOM API is quite similar to the W3C one, you can adapt the same algorithm.
Once the match has been found, you should use DOM Range API to manipulate the content of the DOM nodes. E.g., to wrap a run of plain text with a styled <SPAN>:
var range = document.createRange();
range.setStart(startNode, startOffset);
range.setEnd(endNode, endOffset);
var span = document.createElement("span");
span.style.backgroundColor = "blue"
range.surroundContents(span);
Overall, this task is quite non-trivial and certainly isn't something you can fit into a single page of JavaScript code, to be answered here.
This seems to be somewhat a solution to your problem.
DEMO here: http://jsfiddle.net/bhu9N/5/
$(document).ready(function() {
$("body").on("keyup", ".editable", function(e) {
var $this = $(this);
if(e.keyCode==32) {//space
var words = $this.text().split(' ');
var lastword = $.trim(words[words.length-1]);
var reg = /^#\S+/;
if(reg.test(lastword)) {
//make an AJAX call for checking this word for existence
//suppose data is returned and data==1 means green
var data = 1;
if(data==1) {
var orgtext = $this.html();
orgtext = orgtext.replace(lastword, '<span class="green">'+lastword+'</span>');
$this.html(orgtext);
}
}
}
});
});
Once the text is highlighted, the cursor goes to the starting of the div. So this still needs to be fixed. I will be updating the solution if I am able to find it. Meanwhile, just play around with what I have provided now and see if it helps.
As Ezos pointed out in his answer, I would not recommend trying to do anything intensive (such as making Ajax requests to check if a username exists or not) each time the user releases a key. You might have a bad time. With that said, I would recommend waiting a set amount of time after the user has stopped typing to run through what they've typed and highlight words, for example:
var textarea = $(".smartText");
var highlightWords = function highlightWords() {
var original = textarea.text();
var replaced = original.replace(/#[a-zA-Z0-9]+/g, function (username) {
// Magic
return "<span class='exists'>" + username + "</span>";
});
textarea.html(replaced);
};
var timer;
textarea.keyup(function (e) {
clearTimeout(timer);
if ($(this).text()) {
timer = setTimeout(highlightWords, 1000);
}
});
Link to a fiddle: http://jsfiddle.net/neJLW/
I think the code above should get you started in the right direction. Like you said, the cursor will still jump around so you'll have to save it and reset it in its old position each time you edit the contents of the div. Also, you'll want to adjust the timeout according to how long you expect determining if a username exists to take. You'll need to replace // Magic with your username check and adjust the return value accordingly.
As an aside, you'll want to keep in mind the accessibility issues with wrapping certain things in spans (see this GitHub issue for Lettering.js for an example).
Edit: Also note that this is not a robust solution (it doesn't react to copy paste for example). YMMV.
The method you are using seems very browser intensive and may cause some issues if someone types very quickly and it's running multiple requests before the 'String' can be verified through ajax. You might be better off if you use a library such as http://aehlke.github.io/tag-it/ - You can depict a function to change font color, etc, the same way it recommends a tag.
If i get time, i will make fiddle demo.
I have some text on a page and I want to located and remove any text found in brackets.
For example:
<td>here is [my text] that I want to look at</td>
So I want to grab that text (my text), save it in a variable and remove it from where it is.
If you're using jQuery you could use a regular expression like \[(.+)\] on $('body').text().
EDIT: Sorry, I might have jumped the gun a little bit giving you this answer. Going to think about it for a few more minutes and try to update this with a little more info.
You may find that this task is not all that simple. If you have control over the text before it is sent to the web browser you may want to put a <span class='bracket'>[my text]</span> around the text, then you could easily do something like this with jQuery:
$(".bracket").each(function() {
// store the data from $(this).text();
}).remove();
This can be done using regular expressions and jQuery, but there are problems that may creep up dealing with text inside of attributes like <input name='test[one][]' /> The "simple" regex would be to do something like this:
$("td").each(function() {
var $this = $(this);
var html = $this.html();
var bracketText = [];
// match all bracketed text in the html - replace with an empty string
// but push the text on to the array.
html = html.replace(/\[([^\]]+)\]/g, function() {
bracketText.push(arguments[1]);
return "";
});
// put the new html in away and save the data for later
$this.html(html).data("bracketText", bracketText);
});
There is not much danger in doing this if you're sure you wont have [] inside of tags other than in the text.
I ended up doing the following:
$('#formQuizAnswers td.question').each(function(){
var header = $(this).text().match(/-.*-/);
$(this).text($(this).text().replace(header,''));
});
I changed my text I search for to have dashes around it IE -My text-
This question already has answers here:
How to replace plain URLs with links?
(25 answers)
Closed 9 years ago.
Does anyone know of a script that can select all text references to URLs and automatically replace them with anchor tags pointing to those locations?
For example:
http://www.google.com
would automatically turn into
http://www.google.com
Note: I am wanting this because I don't want to go through all my content and wrap them with anchor tags.
NOTE: An updated and corrected version of this script is now available at https://github.com/maranomynet/linkify (GPL/MIT licence)
Hmm... to me this seems like the perfect task for jQuery.
...something like this came off the top of my mind:
// Define: Linkify plugin
(function($){
var url1 = /(^|<|\s)(www\..+?\..+?)(\s|>|$)/g,
url2 = /(^|<|\s)(((https?|ftp):\/\/|mailto:).+?)(\s|>|$)/g,
linkifyThis = function () {
var childNodes = this.childNodes,
i = childNodes.length;
while(i--)
{
var n = childNodes[i];
if (n.nodeType == 3) {
var html = $.trim(n.nodeValue);
if (html)
{
html = html.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(url1, '$1$2$3')
.replace(url2, '$1$2$5');
$(n).after(html).remove();
}
}
else if (n.nodeType == 1 && !/^(a|button|textarea)$/i.test(n.tagName)) {
linkifyThis.call(n);
}
}
};
$.fn.linkify = function () {
return this.each(linkifyThis);
};
})(jQuery);
// Usage example:
jQuery('div.textbody').linkify();
It attempts to turn all occurrences of the following into links:
www.example.com/path
http://www.example.com/path
mailto:me#example.com
ftp://www.server.com/path
...all of the above wrapped in angle brackets (i.e. <...>)
Enjoy :-)
JQuery isn't going to help you a whole lot here as you're not really concerned with DOM traversal/manipulation (other than creating the anchor tag). If all your URLs were in <p class="url"> tags then perhaps.
A vanilla JavaScript solution is probably what you want, and as fate would have it, this guy should have you covered.
I have this function i call
textToLinks: function(text) {
var re = /(https?:\/\/(([-\w\.]+)+(:\d+)?(\/([\w/_\.]*(\?\S+)?)?)?))/g;
return text.replace(re, "$1");
}
I suggest you do this on your static pages before rendering to the browser, or you'll be pushing the burden of conversion computation onto your poor visitors. :) Here's how you might do it in Ruby (reading from stdin, writing to stdout):
while line = gets
puts line.gsub( /(^|[^"'])(http\S+)/, "\\1<a href='\\2'>\\2</a>" )
end
Obviously, you'll want to think about how to make this as robust as you desire. The above requires all URLs to start with http, and will check not to convert URLs that are in quotes (i.e. which may already be inside an <a href="...">). It will not catch ftp://, mailto:. It will happily convert material in places like <script> bodies, which you may not want to happen.
The most satisfactory solution is really to do the conversion by hand with your editor so you can eyeball and approve all substitutions. A good editor will let you do regexp substitution with group references (aka back references), so it shouldn't be a big deal.
Take a look at this JQuery plugin: https://code.google.com/p/jquery-linkifier/
Doing this server-side is not an option sometimes. Think of a client-side Twitter widget (that goes directly to Twitter API using jsonp), and you want to linkify all the URLs in the Tweets dynamically...
If you want a solution from another perspective... if you can run the pages through php and HTML Purifier, it can autoformat the output and linkify any urls.