I somehow need to trim() the innerHTML of my content... so I have something like this:
<div>
<b>test</b>
123 lol
</div>
I basically want to rid of the white space that is ONLY between <div> and the next character, and the white space just before the closing </div>.
So the outcome would be:
<div><b>test</b>
123 lol</div>
var $mydiv = $('#mydiv');
$mydiv.html($.trim($mydiv.html());
This should take the contents any element, trim the whitespace from it and reset it as the content.
I don't really know why you want to do this but it seems like you are using jquery, so you can use the trim helper:
var $stuff = $(...the messy html you have above including the outer div);
var tidy = $.trim( $stuff.html() );
// tidy has no more div wrapper so you can do this:
return "<div>" + tidy "</div>"
// or this (but i dunno that it won't pad it again)
$stuff.html(tidy)
You can easily write a jQuery plugin to do this. I created both a static and instance method for this.
You can toggle the __DEBUG__TRIM_TYPE variable below to change the technique. Each case will produce the exact same result. They are different ways of achieving the same result.
// jQuery Plugin
// =============================================================================
(function($) {
$.fn.trimHtml = function() {
return this.html(function(index, html) {
return $.trim(html);
});
};
$.trimHtml = function(selector) {
return $(selector || '*').filter(function() {
return $(this).data('trim') === true;
}).trimHtml();
}
}(jQuery));
// Example
// =============================================================================
$(function() {
var __DEBUG__TRIM_TYPE = 1; // You can change this to values between 1-3.
switch (__DEBUG__TRIM_TYPE) {
// Option #1. Select elements by a selector.
case 1:
$('.pre-block[data-trim="true"]').trimHtml();
break;
// Option #2. Filter elements by a selector and their data.
case 2:
$('.pre-block').filter(function() { return $(this).data('trim'); }).trimHtml();
break;
// Option #3. Apply function to all elements where the "trim" data is TRUE.
case 3:
$.trimHtml();
break;
}
});
h1 { font-size: 1.5em; }
.pre-block { display: inline-block; white-space: pre; border: thin solid black; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.js"></script>
<h1>Not Trimmed</h1>
<div class="pre-block" data-trim="false">
Text not to be trimmed.
</div>
<h1>Already Trimmed</h1>
<div class="pre-block" data-trim="false">Text already trimmed.</div>
<h1>Trimmed</h1>
<div class="pre-block" data-trim="true">
Text that was trimmed.
</div>
Related
If you have something simple like this in HTML:
<div class="main">Item 7,000</div>
How to make javascript apply an html element and a class for the 7,000 part (because its numeric) on page load? To something like this:
<div class="main">Item <span class="wrap">7,000</span></div>
Or maybe just an html element, if with class not possible.
I apologies I don't have any code to share right now. I'm still browsing other questions.
Maybe it should be something with jQuery if $.isNumeric() is true then apply element?
There will be edge case but accomplishes your goal
$(function () {
$(".main").each(function (index, element) {
var $element = $(element);
var wrapped = $element.text().replace(/(.+?)((\d{1,3},?)+)/g, '$1<span class="wrap">$2</span>');
$element.html(wrapped);
});
});
.wrap {
background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main">Item 7,000</div>
<div class="main">Item 960</div>
<div class="main">Item 7,000,000</div>
If you use node.textContent you can get the string inside the div
string = document.querySelector('#main').textContent // --> "Item 7,000"
From here you can use Array#split to separate each word:
array = string.split(' '); --> ['Item','7,000']
Now remove the comma and check isNaN for each, return an array w:
newNode = array.map((e)=> isNaN(e.replace(/,/g,"")) ? e : {element:'span', content: e})
Now you have ['Item', { element: 'span', content: '7,000'}] which you can use to generate the contents of the div element in your example...
There might be way better ways to do this, I am just trying to help :)
Use javascript regex find a matching number and replace with span
var regex =/\b(\d+)\b/g
var regex =/\b(\d+)\b/g
var text = document.getElementById("main").innerHTML;
document.getElementById("main").innerHTML = text.replace(regex,'<span class="wrap">$1</span>')
span.wrap{
color:red;
}
<p id="main">Item : 7000</p>
I want to replace all the tags with different tag using javascript.
Lets say I want to replace "asdf" tag with "xyz"
<asdf>
<asdf> First
<asdf> First nested </asdf>
</asdf>
<asdf> Second</asdf
</asdf>
This is what I am expecting:
<xyz>
<xyz> First
<xyz> First nested </xyz>
</xyz>
<xyz> Second </xyz>
</xyz>
i tried with using jquery
$('asdf').each(function() {
$(this).replaceWith("<xyz>"+$(this).html()+"</xyz>")
});
but it replaces only the first not all.
I'd do it in reverse document order so that we process descendant elements before ancestor ones, and I'd avoid making a round-trip through markup since that's unnecessary overhead and will wipe out event handlers we could avoid wiping out. (Not much we can do about the ones on the actual elements we're changing, at least not ones attached with modern techniques.)
See comments:
// Get all target elements, and then get a raw array for them
// and reverse it. Then loop through the reversed copy.
$("div").get().reverse().forEach(function(src) {
// Get a jQuery wrapper for this element
var $src = $(src);
// Create the replacement
var $dest = $("<span>");
// Move all its contents over
$dest.append($src.contents());
// Copy its attributes
Array.prototype.forEach.call(src.attributes, function(attr) {
$dest[0].setAttribute(attr.nodeName, attr.nodeValue);
});
// Replace it
$src.replaceWith($dest);
});
Live Example:
setTimeout(function() {
// Get all target elements, and then get a raw array for them
// and reverse it. Then loop through the reversed copy.
$("div").get().reverse().forEach(function(src) {
// Get a jQuery wrapper for this element
var $src = $(src);
// Create the replacement
var $dest = $("<span>");
// Move all its contents over
$dest.append($src.contents());
// Copy its attributes
Array.prototype.forEach.call(src.attributes, function(attr) {
$dest[0].setAttribute(attr.nodeName, attr.nodeValue);
});
// Replace it
$src.replaceWith($dest);
});
}, 500);
div {
border: 1px solid red;
}
span {
border: 1px solid green;
}
.test {
color: blue;
font-weight: bold;
}
<p>Divs will change to spans in a moment. "Second" is blue because it has a class on it, to check that we copy attributes correctly.</p>
<div>
<div>First
<div>First nested</div>
</div>
<div class="test">Second</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Made simple jquery plugin
$.fn.renameTag = function(replaceWithTag){
this.each(function(){
var outerHtml = this.outerHTML;
var tagName = $(this).prop("tagName");
var regexStart = new RegExp("^<"+tagName,"i");
var regexEnd = new RegExp("</"+tagName+">$","i")
outerHtml = outerHtml.replace(regexStart,"<"+replaceWithTag)
outerHtml = outerHtml.replace(regexEnd,"</"+replaceWithTag+">");
$(this).replaceWith(outerHtml);
});
return this;
}
Usage:
$('asdf').renameTag('xyz')
below is my code, I'm trying to make the content wrapped in div tag change the background color when the mouse curse over it, if the one of the content's variable starts with *. But it doesn't work...
// html
<style>
.normal{background-color: white}
.change{background-color: gainsboro}
</style>
<div ng-mouseover="checkAs(this)" ng-mouseout="this.className='normal'">
......
</div>
// js
$scope.checkAs = function(obj) {
var name = $scope.opportunity.name;
var asterisk = '*';
if(name.startsWith(asterisk)) {
obj.className='change';
} else {
obj.className='normal';
}
};
If you are determined to do this in angular, you would have to call a function through ng-mouseover and in that function, you would need a selector such as JQuery or Javascript's query selector, then modify the element as you see fit. You would have to do something like this (using JQuery):
$scope.checkAs = function() {
$("div").hover(function() {
$(this).prop('background-color','gainsboro');
}, function(){
$(this).prop('background-color','white');
});
};
But, as PSL suggested, the "this" in checkAs(this) won't be the DOM element. A CSS solution might be better:
div :hover{
background-color: gainsboro
}
I have a html code that cannot be altered directly.
<span class="class1 class2 class3 "> First name*: </span>
I need to move the * at the begining or the text. The end result should be this:
<span class="class1 class2 class3 "> *First name: </span>
I also need to make the * to be red (I need to add a class only for this character).
Any ideas?
I'd suggest:
$('span.class1.class2.class3').text(function(i, t){
/* i is in the index of the current element among those returned,
t is the text of the current element.
We return the new text, which is an asterisk, followed by the original text,
with the asterisk removed (using replace to replace the asterisk with an empty string):
*/
return '*' + t.replace(/\*/,'');
});
JS Fiddle demo.
If, however, you need a more generic approach (for example if you have multiple elements with the same/similar selectors):
// selects all the span elements, and filters:
$('span').filter(function(){
// discards the elements that *don't* have '*:' in their text:
return $(this).text().indexOf('*:') > -1;
// iterates over those elements (as above):
}).text(function(i, t) {
return '*' + t.replace(/\*/,'');
});
JS Fiddle demo.
In order to 'make it red,' you'd have to manipulate the HTML, rather than just the text, of the element:
$('span').filter(function(){
return $(this).text().indexOf('*:') > -1;
// Using 'html()' to set the HTML of the 'span' element:
}).html(function(i, h) {
// creating a span and prepending to the current element
return '<span class="required">*</span>' + h.replace(/\*/,'');
});
Coupled with the CSS:
.required {
color: red;
}
JS Fiddle demo.
Further, for simplicity, given that you want to target the * with a class-name (and therefore wrap it in an element-node), you could avoid the string-manipulation and simply float:
$('span').html(function(i,h){
// simply wrapping the `*` in a span (using html() again):
return h.replace(/(\*)/,'<span class="required">*</span>');
});
With the CSS:
.required {
float: left;
color: red;
}
JS Fiddle demo.
References:
filter().
html().
text().
If the problem is the very specific scenario you gave,
$(".class1.class2.class3").each(function() {
var inner = $(this).html();
$(this).html("*" + inner.replace("*",""));
}
var span = $('span.class1.class2.class3');
var new_text = span.text().replace(/\*/, '').replace(/^(\s*)/, '\1<span style="color:red;">*</span>');
span.html(new_text);
Demo
I set out on a journey to create an iTunes-like search using Javascript. I learned about jQuery, and with some help from people on StackOverflow, I was successful.
I've come back here to share with you a very simple way to create a dynamic hide/show list based on the user input.
Let's search!
The entirety of the tutorial code can be found here.
And a JSFiddle for it is here!
So good to see Nick was successful on this experiment. good job on learning how to do it :)
Just in case you haven't encountered this jquery plugin, you might want to take a look at it too it's called Quick search.
https://github.com/riklomas/quicksearch
And I've used it on numerous pages and it works like a charm. example:
http://fedmich.com/works/types-of-project.htm
First, create a simple Div Layout with some text in the divs and search bar above it.
<div class="search_bar">
<form><!--The Field from which to gather data-->
<input id="searchfield" type="text" onclick="value=''" value="Case Sensitive Search">
</form>
</div>
<!--Containers With Text-->
<div class="container">
<div class="container_of_hc">
<div class="horizontal_containers">Cat</div>
<div class="color">Black</div>
<div class="color">White</div>
<div class="color">Orange</div>
</div>
<div class="horizontal_containers">Dog</div>
<div class="horizontal_containers">Rat</div>
<div class="horizontal_containers">Zebra</div>
<div class="horizontal_containers">Wolf</div>
</div>
CSS:
.container {
width: 100%;
}
.horizontal_containers {
height:10%;
border: solid 3px #B30015;
font-size: 45px;
text-align: center;
}
Second, you will make a script utilizing jQuery. Remember the title says this is a Dynamic Search, meaning (for us) we want to update the search with each key typed:
$("#searchfield").keyup(function() {
Note: Need a selector refresher?
Then we will set a variable to the value in #searchfield:
var str = $("#searchfield").val(); //get current value of id=searchfield
To ensure we show all the divs in our list when there is nothing in the searchfield we create an if statement based on the length of our new variable (str):
if (str.length == 0) {
//if searchfield is empty, show all
$(".horizontal_containers").show();
}
Last, we do the actual hiding of the divs if the length of str is not 0:
else {
//if input contains matching string, show div
//if input does not contain matching string, hide div
$("div:contains('" + str + "').horizontal_containers").show();
$("div:not(:contains('" + str + "')).horizontal_containers").hide();
}
});
The div:contains() and div:not(:contains()) statements are what set the conditions. It's essentially an if statement. They search the text contained within the div, not the div attributes. If you want to search a deeper div structure you can use more than one selector in the script's jQuery statements like so:
if (str.length == 0) {
//if searchfield is empty, show all
$(".container .color").show();
} else {
//if input contains matching string, show div
//if input does not contain matching string, hide div
$(".container div:contains('" + str + "').color").show();
$(".container div:not(:contains('" + str + "')).color").hide();
}
Replace the script statement you already have to give it a try.
Note: The nesting structure of your divs must match that in your selector.
And that's essentially it. If you have tips to improve this, know how to change it to a case insensitive search, or anything else you can think of, please let me know!
Thanks to MrXenoType I have learned case insensitivity for the :contains function.
To create a case insensitive search for this project simply add:
$.expr[":"].contains = $.expr.createPseudo(function(arg) {
return function( elem ) {
return $(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
};
});
This creates a pseudo for the contains function. Place this code above your other script (within the same script) to make true for only this script.
Try:
$.expr[":"].contains_nocase = $.expr.createPseudo(function(arg) {
return function( elem ) {
return $(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
};
});
for adding a :contains_nocase() selector with jQuery 1.8