Replace Url value in textbox with regexp - javascript

I have a server size image stream where you pass "fileid", width and height to and it streams an image to client. I'm using CKEditor, and would like to add jquery function that changes it's url when height or width changes in the textboxes.
As you see here on the pic its a specific format:
/Content/Image/{digit}/{width}/{height} rest is optional in string.
Lets say id's of them textboxes are "txtwidth" and "txtheight", how would you add jquery functionality to it that replaces width and height in url textbox, and only if it matches string starting with /Content/Image/{digit}/{width}/{height}?
Thanks in advance
/Lasse

You can do this easily by using regexp to match the string and to replace the corresponding parts. As you mentioned that you'd want to do this with jQuery I am assuming you have jQuery already on your site, but if you don't I wouldn't recommend adding it for this.
Instead of explaining further what to do, I've pasted the code below and commented each step, which should make it quite clear what's going on:
// bind onchange and keypress events to the width and height text boxes
$('#txtwidth, #txtheight').bind('change keypress', function(){
// define the regexp to which to test with, edit as needed
var re = /\/Content\/Image\/([0-9]+)\/[0-9]+\/[0-9]+\//,
// store url and its value to a variable so we won't have to retrieve it multiple times
url = $('#url'),
val = url.val();
// test if regexp matches the url
if (!re.test(val)) {
// doesn't match
return;
}
// we got this far, so it did match
// replace the variables in the regexo
val = val.replace(re, "/Content/Image/$1/" + $("#txtwidth").val() + "/" + $("#txtheight").val() + "/");
// put it back into the input field
url.val(val);
});
example: http://jsfiddle.net/niklasvh/wsAcq/

Let's say that the URL field has the HTML id "fileUrl". The regular expression equivalent to its value is:
/^\/Content\/Image\/(\d+)\/(\d+)\/(\d+)/
Here is a quick proposal (not tested and not optimized at all):
$("#txtwidth").change(function()
{
var value=$("#fileUrl").val();
$("#fileUrl").val(value.replace(/^\/Content\/Image\/(\d+)\/(\d+)\/(\d+)/, "/Content/Image/$1/"+$("#txtwidth").val()+"/$3"));
});
$("#txtheight").change(function()
{
var value=$("#fileUrl").val();
$("#fileUrl").val(value.replace(/^\/Content\/Image\/(\d+)\/(\d+)\/(\d+)/, "/Content/Image/$1/$2/"+$("#txtheight").val()));
});

i was going to suggest /(\d+)/g
<div id="replace_this">/Content/Image/56/1024/768</div>
var newWidth = 2048;
var newHeight = 384;
var matches = $('#replace_this').html().match(/(\d+)/g);
newHTML = $('#replace_this').html().replace(matches[1], newWidth);
newHTML = newHTML.replace(matches[2], newHeight);
$('#replace_this').html(newHTML);
http://jsfiddle.net/qpmuT/

I was going to suggest a similar approach as Niklas' answer (before I was interrupted by something important, or possibly a squirrel). So go with that (and +1 from me).
A couple of points, though:
Validate the contents of the width and height fields. Or at least use parseInt. Otherwise, if the user enters a non-digit character, the regular expression will stop matching...
Match on [0-9]* instead of [0-9]+. The latter would break the regex if the user left a field empty. Of course, doing val = parseInt(...) || 0 would fix it as well.
In other words, I'd do something like this:
JSFiddle: http://jsfiddle.net/PPvG/j8dT9/
var re = /\/Content\/Image\/([0-9]*)\/[0-9]*\/[0-9]*\//,
url = $('#url'),
val = url.val(),
width = parseInt($("#txtwidth").val(), 10) || 0,
height = parseInt($("#txtheight").val(), 10) || 0;
if (re.test(val)) {
val = val.replace(re, "/Content/Image/$1/" + width + "/" + height + "/");
url.val(val);
}
Also, in case the path (/Content/Image/) might change in the future, you could use this more general regex: /^\/(.+)\/([0-9]*)\/[0-9]*\/[0-9]*\// and let the replacement string start with /$1/$2/. (See this JSFiddle.)
Finally, I wouldn't bind to keypress. Aside from possible side effects in some browsers (like the change event not being handled), there is a UX concern. Most users are used to input widgets handling their input on blur, because their native apps work that way. Besides, many users look at their keyboard when typing numbers (numpads are getting rare, these days).

Related

What is the best way to access an element through a data-attribute whose value is an object (JSON)?

Say I have the following element:
<div class='selector' data-object='{"primary_key":123, "foreign_key":456}'></div>
If I run the following, I can see the object in the console.
console.log($('.selector').data('object'));
I can even access data like any other object.
console.log($('selector').data('object').primary_key); //returns 123
Is there a way to select this element based on data in this attribute? The following does not work.
$('.selector[data-object.foreign_key=456]');
I can loop over all instances of the selector
var foreign_key = 456;
$('.selector').each(function () {
if ($(this).data('object').foreign_key == foreign_key) {
// do something
}
});
but this seems inefficient. Is there a better way to do this? Is this loop actually slower than using a selector?
You can try the contains selector:
var key_var = 456;
$(".selector[data-object*='foreign_key:" + key_var + "']");
I think that you may gain a little speed here over the loop in your example because in your example jQuery is JSON parsing the value of the attribute. In this case it's most likely using the JS native string.indexOf(). The potential downside here would be that formatting will be very important. If you end up with an extra space character between the colon and the key value, the *= will break.
Another potential downside is that the above will also match the following:
<div class='selector' data-object="{primary_key:123, foreign_key:4562}"></div>
The key is clearly different but will still match the pattern. You can include the closing bracket } in the matching string:
$(".selector[data-object*='foreign_key:" + key_var + "}']");
But then again, formatting becomes a key issue. A hybrid approach could be taken:
var results = $(".selector[data-object*='" + foreign_key + "']").filter(function () {
return ($(this).data('object').foreign_key == foreign_key)
});
This will narrow the result to only elements that have the number sequence then make sure it is the exact value with the filter.
With a "contains" attribute selector.
$('selector[data-object*="foreign_key:456"]')

Javascript/jQuery - Need to find raw text on the page, capture what follows into variable, and replace original with HTML

So let’s say the text KEYWORDANIMAL:(Cat) appears on a page. I want to search through the page for all instances of KEYWORDANIMAL, and then pull the actual animal, in this case Cat, into a variable to be used in another script that’ll pull in related content. I also want to replace KEYWORDANIMAL:(Cat) with an empty div with concatenated ID to be targeted by the other script (this other script is already working fine by itself).
I've been using info from several other threads here but just cannot make it all come together.
-Find text string using jQuery?
-Get text from character and after using jQuery
-How do I use JQuery to replace all occurring of a certain word in a webpage?
Here's what I have so far:
<p>Here is an animal: KEYWORDANIMAL(Cat)</p>
var findString = $('p:contains("KEYWORDANIMAL")').html();
var startIDString = findString.indexOf('(') + 1;
var endIDString = findString.indexOf(')');
var animalID = findString.substring(startIDString, endIDString);
var embedString1 = "<div id=\"";
var embedString2 = "\"></div>";
var embedStringFull = embedString1 + "animal" + animalID + embedString2;
alert(embedStringFull);
findString.each(function () {
var newDIV = $(this).html().replace('KEYWORDANIMAL', embedStringFull);
$(this).html(newDIV);
});
In fiddle form: http://jsfiddle.net/dC6bj/1/
I got the find part down (probably not very efficiently though), but I am clearly missing something on the replace.
If you absolutely have to do this with JavaScript, you can use a regex replacement function:
var animal_regex = /KEYWORDANIMAL\((.*?)\)/g;
$('p:contains("KEYWORDANIMAL")').each(function() {
var $this = $(this);
var html = $this.html().replace(animal_regex, function(match, name) {
return '<div id="animal' + name + '"></div>';
});
$this.html(html);
});
Demo: http://jsfiddle.net/dnuaL/
This should be done serverside, if possible.
For your third question on how toreplace all occurences of a certain word in a webpage use Regex.Replace like this:
var pagecontent = $('body').html();
var newcontent = Regex.Replace(pagecontent , #"[cat]", "dog");
&('body').html(newcontent);
Regex is the fastest solution for this kind of stuff.
My code example is a bit simple, it would also replace ocurrences within a tag.
or within a word for example in catamaran or .
To make it more perfect you could look for cat preceded by a space and followed by a space or a point or a comma. Read some regex tutorials for this. (It's really worth learning, once you know how to, you'll use it a lot)
Goodluck!

Jquery/Javascript - Syntax highlighting as user types in contentEditable region

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.

Is it possible to have jQuery do a mathematical calculation from a DIV's numerical content?

I have a DIV that is fed by a server side script that I don't have access too, and it outputs the value in £'s.
HTML Example:
<div id="totalExpenditure">£1,125</div>
I then want to have a jQuery script take that figure and workout the difference between a set value of £2,000 and result it to another DIV.
Which says: <div id="totalSurplus">You have £725 remaining.</div>
I've searched Google for mathmatic jQuery but the results look far too complex. What I'm not sure is even possible is to convert the output of the ID totalExpenditure into the DOM to be manipulated.
1) get the string: var myVal = $('#totalExpenditure').text()
2) Get rid of the non-numeric pound sign: myVal = myVal.replace('£','') and the comma myVal = myVal.replace(',','')
3) turn it into an number: myVal = parseFloat(myVal)
4) Perform any math you want with myVal.
You can do this all in one step, but this gives you an idea of how the language works.
You've got two issues here.
First you need to parse a string and convert it to a number.
Then you need to perform the calculation.
Neither of these are really jquery specific. JQuery can help with getting the string, and writing the output, but the rest is just pure javascript.
var num = parseFloat($("#totalExpenditure").text().replace("£", ""));
var remain = 2000 - num;
var outputStr = "You have £" + remain.toFixed(2) + " remaining";
$("#totalSurplus").text(outputStr);
For more control over the output of the currency perhaps check out this post: How can I format numbers as money in JavaScript?
You are able to feed the value (£1,125) from the server to the client's JavaScript engine the same way you're feeding HTML to the client.
It is really not recommended to read a DOM element for a text node and interpret said node as a value for mathematical operations. You should have a JavaScript variable aside to calculate this for you.
obtain the totalExpenditure div content and set totalExpenditure var value (using a regex):
var content = $('#totalExpenditure').text();
var pattern = /[0-9\.,]/g;
var totalExpenditure = pattern.exec(content);
subtract
var totalImport = 2000;
var result = totalImport - totalExpenditure;

Matching a list of possible hashtags in a tweet - Javascript or jQuery

Firstly I've looked at a lot of posts on Stackoverflow but I don't see one which seems to be the definitive way. Someone always seems to find a flaw in the regex.
I already have retrieved my tweets and obviously they can contain any number of hashtags in each one.
If I have an array of possible hashtags that I want to find - ["#ENGLAND","#IRELAND","#wales"] etc.
What is a RELIABLE way to check if a tweet contains these hashtags. I don't want to call the API again, I only want to check my existing tweets, as I'm clicking on buttons to change the filtering on the fly, want to avoid rate limit if they keep clicking around for ages.
EDIT:
Example: Here is a tweet that contains #ENGLAND and #someothertag
I want to search all the tweets and just show the tweets that CONTAIN one or more of my array of tags, I already cache the tweets, I don't want to make a call containing any tags just filter the existing results!
Why only hashify particular hashtags (which you need to specify and then maintain) when you can hashify any hashtag?
I usually use something like this:
var hashregex = /#([a-z0-9_\-]+)/gi,
text = text.replace(hashregex, function (value) {
return '<a target="_blank" href="http://twitter.com/#!/search?q=' + value.replace('#', '%23') + '">' + value + '</a>';
});
Then you can just use text when you set the content to the processed tweets
You could store the hashtags from the entities on the element, for instance
<div class='tweet' data-hashtags='england ireland'>some_tweet</div>
And filter like this when someone clicks your button:
$('div.tweet').hide();
$('div.tweet[data-hashtags~="ireland"]').show();
It's obviously greatly simplified, but the general approach should help you avoid having to parse out the tags yourself
// match a #, followed by either "question" or "idea"
var myregexp = /#(england|ireland|wales)\b/i;
var match = myregexp.exec(subject);
if (match != null) {
result = match[1]; // will contain "england","ireland", or "wales"
} else {
result = "";
}
If you don't know the names of the hashtags on hand
replace
var myregexp = /#(england|ireland|wales)\b/i;
with
var myregexp = /#(\w+)/; // Use this instead

Categories

Resources