I am trying to write a simple javascript function to pull just img urls out of text.
i have nearly got it working but i am having a issue with params how can i remove them and also returning the full img url, could someone help not the best at regexs
document.write(getImagesInText("Whether the view should hidden from (i.e., ignored by) the accessibility service. http://jsfiddle.net/ http://thickbox.net/images/plant4.jpg afhttp://thickbox.net/images/plant4.jpg?4t34t34t"));
function getImagesInText(text){
var html = text;
var urlRegex = /((ftp|http|https):\/\/(\w+:{0,1}\w*#)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%#!\-\/]))?)+\.(?:jpg|jpeg|gif|png)/gi;
return html.replace(urlRegex, '<img src="$1" width="48" height="48"/>');
}
view the example here.
http://jsfiddle.net/7dJCm/1/
UPDATE
function getImagesInText( s ) {
var html = s;
var imgregex = /((http(s)?|ftp):\/\/[\S]*(\.jpg|.jpeg|\.gif|.png)[\S]*)/gi;
var urlRegex = /((ftp|http|https):\/\/(\w+:{0,1}\w*#)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%#!\-\/]))?)/gi;
html = html.replace(/(\.jpg|\.jpeg|\.gif|\.png)/gi, function( ext ) { return ext + " "; });
html = html.replace(/(http|https)/gi, function( ext ) { return " " + ext; });
html = html.replace(urlRegex, function( path ) {
if(path.match(/jpg|png|gif|jpeg/g)){
return "<img width='48' height='48' src='" + path + "' />";
}else{
return "<a href='" + path + "'>" + path + "</a>";
}
});
return html;
}
http://jsfiddle.net/7dJCm/16/
var s = "Whether the view should hidden from (i.e., ignored by) the accessibility service. http://jsfiddle.net/ http://thickbox.net/images/plant4.jpg afhttp://thickbox.net/images/plant4.jpg?4t34t34t";
console.log( getImagesInText(s) ) // "Whether the view should hidden from (i.e., ignored by) the accessibility service. http://jsfiddle.net/ <img src='http://thickbox.net/images/plant4.jpg' /> af<img src='http://thickbox.net/images/plant4.jpg?4t34t34t' />"
function getImagesInText( s ) {
var regex = /((http(s)?|ftp):\/\/[\S]*(\.jpg|\.jpeg|\.gif|\.png)[\S]*)/gi;
return s.replace(regex, function( path ) {
return "<img src='" + path + "' />";
});
}
Related
I'm trying to run the following script on a specific Wordpress page, but it's not working. The script does work but when not applied to the specific page. Yes the page id is correct. What did I do wrong? Thanks in advance.
<?php if (is_page('page-id-48857') ):?>
<script>
jQuery(document).ready(function ($) {
$(function () {
var $content = $('#jsonContent');
var data = {
rss_url: 'https://inside.calpoly.edu/feed'
};
$.get('https://api.rss2json.com/v1/api.json', data, function (response) {
if (response.status == 'ok') {
var output = '';
$.each(response.items, function (k, item) {
output += '<div class="post-card category-medium published">';
//output += '<h3 class="date">' + $.format.date(item.pubDate, "dd<br>MMM") + "</h4>";
var tagIndex = item.description.indexOf('<img'); // Find where the img tag starts
var srcIndex = item.description.substring(tagIndex).indexOf('src=') + tagIndex; // Find where the src attribute starts
var srcStart = srcIndex + 5; // Find where the actual image URL starts; 5 for the length of 'src="'
var srcEnd = item.description.substring(srcStart).indexOf('"') + srcStart; // Find where the URL ends
var src = item.description.substring(srcStart, srcEnd); // Extract just the URL
output += '<p class="post-meta">';
//output += '<span class="published">' + item.pubDate + '</span>';
output += '#inside.calpoly.edu</span>';
output += '</p>';
output += '<h2 class="entry-title">' + item.title + '</h2>';
//output += '<div class="post-meta"><span>By ' + item.author + '</span></div>';
var yourString = item.description.replace(/<img[^>]*>/g,""); //replace with your string.
var maxLength = 300 // maximum number of characters to extract
//trim the string to the maximum length
var trimmedString = yourString.substr(0, maxLength);
//re-trim if we are in the middle of a word
trimmedString = trimmedString.substr(0, Math.min(trimmedString.length, trimmedString.lastIndexOf(" ")))
output += '<div class="excerpt">'+trimmedString + '</div>';
output += 'Read More';
output += '<a class="entry-featured-image-url" href="'+ item.link + '"><img src="' + src + '"></a>';
output += '</div>';
return k < 1;
});
$content.html(output);
}
});
});
</script>
<?php endif; ?>
You are passing in an invalid ID to the is_page() function.
Based off of your code sample, you should be using an integer for your post ID and not a string and also not the 'page-id' portion.
https://developer.wordpress.org/reference/functions/is_page/
Here's some example usages:
// When any single Page is being displayed.
is_page();
// When Page 42 (ID) is being displayed.
is_page( 42 );
// When the Page with a post_title of "Contact" is being displayed.
is_page( 'Contact' );
// When the Page with a post_name (slug) of "about-me" is being displayed.
is_page( 'about-me' );
In your case you should be using:
<?php if (is_page(48857) ):?>
WordPress' is_page() function requires a "Page ID, title, slug, or array of such.". 'page-id-48857' is the body class, you need to just use is_page( 48857 ) since the actual ID is just 48857.
Also note that you should seriously consider using wp_enqueue_script() instead of coding in a custom script tag. It will save you countless headaches in the future.
on line 30 i am facing an issue with $.each(data.menu, function (). I am being told by the console that "data is null". can anyone explain whats going on? thanks
function getFoodMenuData () {
var url = 'http://localhost:8888/Tom_Carp_Final_Project/Chorizios/foodMenu.json';
$.getJSON(url, function (data) {
window.localStorage.setItem('choriziosMenu333', JSON.stringify(data));
});
}
function showFoodMenuData () {
var data = JSON.parse(window.localStorage.getItem('choriziosMenu333'));
var images = "";
$.each(data.menu, function () {
images += '<li class="list-group-item"><img style="width: 100%;" src= "' + this.url + '"></li>';
images += '<li class="list-group-item">' + this.description + '</li>';
});
$('#foodMenu').append(images);
}
showFoodMenuData();
You have to call getFoodMenuData(), and then inside the callback for the asynchronous $.getJSON, call showFoodMenuData().
function getFoodMenuData() {
var url = 'http://localhost:8888/Tom_Carp_Final_Project/Chorizios/foodMenu.json';
$.getJSON(url, function(data) {
window.localStorage.setItem('choriziosMenu333', JSON.stringify(data));
showFoodMenuData(); // <--- call this inside the callback
});
}
function showFoodMenuData() {
var data = JSON.parse(window.localStorage.getItem('choriziosMenu333'));
var images = "";
$.each(data.menu, function() {
images += '<li class="list-group-item"><img style="width: 100%;" src= "' + this.url + '"></li>';
images += '<li class="list-group-item">' + this.description + '</li>';
});
$('#foodMenu').append(images);
}
getFoodMenuData(); // <--- call this first
I wouldn't use $ for the loop. I am not sure of the structure of the data you are receiving but you will probably need a nested loop to get all the data either way this should do the trick.
As a point the for in loop works great for objects. One reason is that the iterator is the key in the object. In this example if you console.log( ii ) inside the second loop you will see either name or url.
HTML
<ul></ul>
Javascript
var menu = {
item1 : {
name : "Food1",
url : "https://s-media-cache-ak0.pinimg.com/736x/79/82/de/7982dec0cc2537665a5395ac18c2accb.jpg"
},
item2 : {
name : "Food2",
url : "http://i.huffpost.com/gen/1040796/images/o-CANADIAN-FOODS-facebook.jpg"
}
};
$( document ).ready( function () {
for ( var i in menu ) {
for ( var ii in menu[ i ] ) {
var elem = ii === "name" ? "<p>" + menu[ i ][ ii ] + "</p>" : "<img src=" + menu[ i ][ ii ] + " height='100px'/>"
$( "ul" ).append( "<li>" + elem + "</li>" );
}
}
});
https://jsfiddle.net/dh3ozpxk/
I'm currently using the jQuery get method to read a table in another page which has a list with files to download and links to others similar webpages.
$.get(filename_page2, function(response, status){
var data = $("<div>" + response + "</div>");
var target_element = data.find(target_element_type_page2 + '#' + target_element_id_page2)[0];
var container = document.getElementById(element_change_content_page1);
if (typeof target_element !== "undefined"){
var rows = target_element.rows;
for (var i = 1, n = rows.length; i < n; i++) {
var table = rows[i].cells[1].getElementsByTagName("TABLE")[0];
var isFolder = table.getAttribute("CType") == "Folder";
var elem = table.rows[0].cells[0];
var text = elem.innerText || elem.textContent;
var link = elem.getElementsByTagName("A")[0].getAttribute("href");
if (!isFolder) {
container.innerHTML += "<li class=\"mainfolderfile\">" + "<a class=\"filelink\" href=\"" + link + "\">" + text + "</a></li>";
} else {
container.innerHTML += "<li class=\"folderlist\">" + "<a class=\"folderlink\" onclick=\"open_submenu(this)\" href=\"#\">" + text + "</a><ul></ul></li>";
var elem_page1 = container.getElementsByTagName("li");
var container_page1 = elem_page1[elem_page1.length - 1].getElementsByTagName("ul")[0];
create_subfolder(container_page1, link);
}
}
} else {
container.innerHTML += "<li class=\"mainfolderfile\">" + "<a class=\"filelink\" href=\"" + "#" + "\">" + "Error..." + "</a></li>";
}
}, page2_datatype);
This is working fine, and all the folders and files are being listed. But when I try to do the same thing with the folders (calling the create_subfolder function) and create sublists with their subfolders and files, I'm getting a weird behavior.
function create_subfolder(container2, link1) {
$.get(link1, function(response, status){
var data = $("<div>" + response + "</div>");
var target_element = data.find("table" + "#" + "onetidDoclibViewTbl0")[0];
if (typeof target_element !== "undefined"){
var rows = target_element.rows;
for (var i = 1, n = rows.length; i < n; i++) {
var table = rows[i].cells[1].getElementsByTagName("TABLE")[0];
var elem = table.rows[0].cells[0];
var text = elem.innerText || elem.textContent;
var link2 = elem.getElementsByTagName("A")[0].getAttribute("href");
//nothing is changed in the webpage. The modifications in the html don't appear
container2.innerHTML += "<li>" + text + "</li>";
}
}
alert(container2.innerHTML); // Print the html with all the modifications
}, "html");
}
The second get(), inside the create_subfolder() function are not changing anything in the webpage, so no sublist is created. But, when I call the alert() function at the end of the get() function, it prints the code with all the modifications it should have made in the html at the second get callback. I believe the problem is related with the asynchronous behavior of the get function but I don't know exactly why. Any guess?
This is a common occurence when I code...I see some code that looks kind of alike..and I know that it is obviously not good to have redundant functionality in my code.
However , is this absolute? 0 Redundancy? I have two functions below, which look kind of alike. ViewH.bookmark and ViewH.tweet.
I'm trying to decide if I should pull out the common functionality into a function called ViewH.mark().
EDIT
var ViewH = {
MARK:
{
FIELD: '|',
ROW: '||',
PASS: '<xx_p>',
FAIL: '<xx_f>'
},
return_string: '',
mark: function(passed_function, embeddedAml)
{
var return_string,
first_split,
element_count,
second_split;
return_string = '';
first_split = embeddedAml.split( ViewH.MARK.ROW );
for( element_count=0; element_count < first_split.length; element_count++)
{
second_split = first_split[element_count].split( ViewH.MARK.FIELD );
passed_function(second_split);
}
return ViewH.return_string;
},
bookmark: function ( embeddedAml )
{
ViewH.return_string='';
return ViewH.mark(ViewH.bookmark_inner, embeddedAml);
},
tweet: function ( embeddedAml )
{
ViewH.return_string='';
return ViewH.mark(ViewH.tweet_inner, embeddedAml);
},
portfolio: function ( embeddedAml )
{
ViewH.return_string='';
return ViewH.mark(ViewH.portfolio_inner, embeddedAml);
},
bookmark_inner: function ( second_split )
{
ViewH.return_string = ViewH.return_string
+ '<img name="bo_im" class="c" src="'
+ 'http://www.google.com/s2/favicons?domain='
+ second_split[0]
+ '" onerror="Arc.BookmarkError(this)"><a target="_blank" name="bookmark_link" class="b" href = "'
+ second_split[1]
+ '">'
+ second_split[2]
+ '</a>';
},
tweet_inner: function ( second_split )
{
ViewH.return_string = ViewH.return_string
+ '<div class="Bb2b"><img class="a" src="'
+ Constant.PICTURES + second_split[ 0 ]
+ '.jpg" alt=""/><a class="a" href="javascript:void(0)\">'
+ second_split[ 1 ]
+ ' posted '
+ ViewH.pretty( second_split[ 2 ],second_split[ 3 ] )
+ '</a><br/><p class="c">'
+ second_split[ 4 ]
+ '</p></div>';
},
portfolio_inner: function ( second_split )
{
if( ( second_split[ 1 ] === 'docx' ) || ( second_split[ 1 ] === 'xlsx' ) )
{
ViewH.return_string = ViewH.return_string
+ '<img name="bo_im" class="c" src="'
+ Constant.IMAGES + second_split[1]
+ '.ico"><a target="_blank" name="bookmark_link" class="b" href = "/'
+ Constant.ROOT
+ second_split[1]
+ '/'
+ second_split[0]
+ '.'
+ second_split[1]
+ '">'
+ second_split[0]
+ '.'
+ second_split[1]
+ '</a>';
}
else
{
ViewH.return_string=ViewH.return_string
+ '<simg name="bo_im" class="c" src="'
+ Constant.IMAGES
+ 'generic'
+ '.ico"><a target="_blank" name="bookmark_link" class="b" href = "'
+ Constant.TEXT
+ second_split[0]
+ '.txt">'
+ second_split[0]
+ '.'
+ second_split[1]
+ '</a>';
}
},
This is a great question, but there is no answer that will apply to all cases. It really is going to depend on what your code looks like. Redundancy is generally to be avoided but it is sometimes worse to over-engineer your code and try to make it fit into a box that it does not really fit into.
In your case you could definitely benefit from taking common code and pulling it into a common method. It looks like the only difference between your methods is the rendering part and it would be simple to pass a rendering function into your "mark" method.
Your "mark" method would look a bit like this:
mark: function(embeddedAml, renderer) {
var return_string,
first_split,
element_count,
second_split;
return_string = '';
first_split = embeddedAml.split( ViewH.MARK.ROW );
for( element_count=0; element_count < first_split.length; element_count++)
{
second_split = first_split[element_count].split( ViewH.MARK.FIELD );
return_string = return_string + renderer(second_split);
}
return return_string;
}
You would keep your bookmark and tweet methods but they would change as well:
bookmark: function (embeddedAml) {
return this.mark(embeddedAml, function(data) {
return '<img name="bo_im" class="c" src="' +
'http://www.google.com/s2/favicons?domain=' +
data[0] +
'" onerror="Arc.BookmarkError(this)"><a target="_blank" name="bookmark_link" class="b" href = "' +
data[1] + '">' +
data[2] + '</a>'
});
}
Now your rendering code (the only code that was different) is controlled independently, but the code that overlapped is in a common place and if it changes you only have to update it in one place.
Generally, yes.
One deciding factor is whether the code is similar coincidentally, or because it performs a similar task. If the latter is true, should you change the functionality of one in the future (particularly that part of the functionality which is shared), will you also want to change the functionality in the other? If so, that makes your decision easy - merge the code where you can.
Even if the code is similar coincidentally, it may still make sense to create a generic library function that cleans up your code.
I would definitely attempt to combine them. You'll notice that the body of the for loop is the only thing that's different between the two. Here's one approach (most of ViewH elided):
var ViewH = {
bookmark: function(embeddedAml) {
return ViewH.combinedFunc(embeddedAml, function(parts) {
return '<img name="bo_im" class="c" src="' +
'http://www.google.com/s2/favicons?domain=' +
parts[0] +
'" onerror="Arc.BookmarkError(this)"><a target="_blank" name="bookmark_link" class="b" href = "' +
parts[1] + '">' +
parts[2] + '</a>';
});
},
combinedFunc: function (embeddedAml, handler) {
var return_string,
first_split,
element_count,
second_split;
return_string = '';
first_split = embeddedAml.split(ViewH.MARK.ROW);
for(element_count=0; element_count < first_split.length; element_count++) {
second_split = first_split[element_count].split(ViewH.MARK.FIELD);
return_string = return_string + handler(second_split);
}
return return_string;
},
}
You could easily do the same thing for tweet. Clearly, you'll want to name the function something better than combinedFunc, but you'll need to choose that name based on context.
Is there a better, more concise way to do this:
function getTweets(){
$.getJSON("http://search.twitter.com/search.json?callback=?&q=superfad",
function(data){
tweetsLoaded = true;
$.each(data.results, function(i,item){
var textPlain = item.text;
var textLinked = linkify(textPlain);
var textHashed = hashify(textLinked);
var textListed = listify(textHashed);
function linkify(tweet){
return tweet.replace(/(http:\/\/[^\s]*)/g, "<a class='twtr-link' target=\"_blank\" href=\"$1\">$1</a>");
}
function hashify(tweet){
return tweet.replace(/(^|\s+)#(\w+)/gi, function(m, before, hash) {
return before + '<a target="_blank" class="twtr-hashtag" href="http://twitter.com/search?q=%23' + hash + '">#' + hash + '</a>';
});
}
function listify(tweet) {
return tweet.replace(/\B[#@]([a-zA-Z0-9_]{1,20})/g, function(m, username) {
return '<a target="_blank" class="twtr-atreply" href="http://twitter.com/intent/user?screen_name=' + username + '">#' + username + '</a>';
});
}
$("#twitter_results").append('<li class="twitter"><img class="twitter_img" src="' + item.profile_image_url + '"/>'+ textListed + '</li>');
});
});
} //end getTweets
// define this globally
function stuffify(match, group1, group2) {
switch (group1 || group2) {
case 'http':
return '<a class="twtr-link" target="_blank" href="' + match + '">' + match + '</a>';
case '#':
return '<a class="twtr-hashtag" target="_blank" href="http://twitter.com/search?q=' + encodeURIComponent(match) + '">#' + match + '</a>'
case '#':
return '<a class="twtr-atreply" target="_blank" href="http://twitter.com/intent/user?screen_name=' + encodeURIComponent(match) + '">#' + match + '</a>';
default:
return match;
}
}
function(data){
tweetsLoaded = true;
var interestingParts = /(http):\/\/\S+|(#|#)[^\s.,!?;^()\[\]<>{}]+/g;
$.each(data.results, function(i,item) {
var newText = item.text.replace(interestingParts, stuffify);
$("#twitter_results").append('<li class="twitter"><img class="twitter_img" src="' + item.profile_image_url + '"/>'+ newText + '</li>');
});
}
I would realign the code such that the text manipulation functions (linkify, hashify, listify) are not inside of the each function, nor are they even inside of getTweets itself. If it's in getTweets, then every time you call that function they have to be redefined. Worse, inside of the each where you had them, those functions are redefined for every item in the returned tweet-set.
Also, there is no need to store the return of each of those functions in it's own var since you only use them once afterward and aren't performing any checks before using them. Just nest the function calls.
Finally, since you're calling append over and over on the same element (inside the each) I pre-queried that element instead of querying for it every time the each function is executed
Those changes, along with some things I do for my own performance preferences are exhibited in the code sample pasted below.
There are other things I would do, however I won't show them here--you can see it in my posted answer at Trouble Converting jQuery Script to Plugin -- a question about making a jQuery plugin which does the same ting as your code). You should store the formatted tweets in an array rather than append each as you get it. Having built that array, you should then combine it into one string and call append once with that string. Making this a jQuery plugin would also be nice for you as it would not require you modify the code to change the targeted DOM element. Looking into use of String.prototype.link would be good as well.
(demo: http://jsfiddle.net/JAAulde/fQ3Lp/2/ )
var getTweets = ( function()
{
/* Privatized text manipulation functions */
var linkify = function( tweet )
{
return tweet.replace( /(http:\/\/[^\s]*)/g, "<a class='twtr-link' target=\"_blank\" href=\"$1\">$1</a>" );
};
var hashify = function( tweet )
{
return tweet.replace( /(^|\s+)#(\w+)/gi, function(m, before, hash)
{
return before + '<a target="_blank" class="twtr-hashtag" href="http://twitter.com/search?q=%23' + hash + '">#' + hash + '</a>';
} );
};
var listify = function( tweet )
{
return tweet.replace(/\B[#@]([a-zA-Z0-9_]{1,20})/g, function(m, username)
{
return '<a target="_blank" class="twtr-atreply" href="http://twitter.com/intent/user?screen_name=' + username + '">#' + username + '</a>';
} );
};
var $twitterResultTarget = $( "#twitter_results" );
/* The actual function which is stored in `getTweets` */
return function()
{
$.getJSON( "http://search.twitter.com/search.json?callback=?&q=superfad", function( data )
{
tweetsLoaded = true;
$.each( data.results, function( i, item )
{
$twitterResultTarget
.append( [
'<li class="twitter"><img class="twitter_img" src="',
item.profile_image_url,
'"/>',
listify( hashify( linkify( item.text ) ) ),
'</li>'
].join( '' ) );
} );
} );
}
}() );
Try to avoid using anonymous functions, its always less confusing if they all have names and are declared outside of any other functions.
I'd probably write in in the jQuery plugin style, and use split as opposed to replace with HTML in callbacks:
(function($){
function getTweets(q) {
var
$set = this,
prefixes = {
'h': 'h',
'#': 'http://twitter.com/search?q=%23',
'#': 'http://twitter.com/intent/user?screen_name='
},
classes = {
'h': 'twtr-link',
'#': 'twtr-hashtag',
'#': 'twtr-atreply'
};
$.getJSON(
"http://search.twitter.com/search.json?callback=?&q=" + encodeURIComponent(q),
function(data){
$.each(data.results, function(i, item){
var
$li = $('<li class="twitter"></li>')
.append('<img class="twitter_img" src="' + item.profile_image_url + '"/> ');
$.each(
item.text.split(
/(\s+)|(https?:\/\/[^\s]*)|(#\w+)|(#[a-zA-Z0-9_]{1,20})/g
),
function(i, chunk) {
if (/^(https?:\/\/|#|#)/.test(chunk)) {
$('<a target="_blank"></a>')
.addClass(classes[chunk[0]])
.attr('href', prefixes[chunk[0]] + chunk.substr(1))
.text(chunk)
.appendTo($li);
} else if (chunk) {
$li.append(document.createTextNode(chunk));
}
}
);
$li.appendTo($set);
});
}
);
}
$.fn.getTweets = getTweets;
})(jQuery);
Then call it like this:
$('#twitter_results').getTweets('superfad');
My $0.02