Troubles trying to add attributes with jquery - javascript

I need to add dynamically a row in jquery, this is my code:
var row = $('<tr />')
.append($('<td />'))
.append($('<td>' + response.nome + '</td>'))
.append($('<td />', {
style: "text-align:center"
}).append($('<input />', {
type: 'image',
src: 'nienteico.png',
'class': 'ajaxEdit',
id: '1.' + response.row_id
}).css({
cursor: 'pointer',
width: '40px',
height: '40px',
}).click(function() {
cambiastato('1.' + response.row_id);
})));
In particular, as regards the last element i'm expecting to get 'id' attribute and one 'onclick function'. Something like:
<tr>
<td></td>
<td>uytredsgfh</td>
<td style="text-align:center">
<input type="image" src="nienteico.png" style="cursor:pointer; width:40px; height:40px" id="1.15" class="ajaxEdit" onclick="cambiastato(1.15)">
</td>
</tr>
The first two elements are correctly written, but unfortunally this is what i get for the last one (id attribute and onclick function missed!)
<td style="text-align:center">
<input type="image" src="nienteico.png" class="ajaxEdit" style="cursor: pointer; width: 40px; height: 40px;">
</td>
Any help or suggestions? Thanks

This is what you would expect.
Your id is invalid because it starts with a number - see w3.org. jQuery is probably rejecting it because of this.
The click event is not written as an attribute of the tag. Instead it is hooked up as a property of the DOM element the tag represents. You will probably find that it works if you put the input on the page and click it.
If you do want to explicitly output the onclick and other attributes into the tag, you can just set them in the initial tag creation call:
var row = $('<tr />')
.append($('<td />'))
.append($('<td>' + response.nome + '</td>'))
.append($('<td style="text-align:center" />')
.append($('<input onclick="cambiastato(1.' + response.row_id + ');" type="image" src="nienteico.png" class="ajaxEdit" id="1.' + response.row_id + '" />')
.css({
cursor: 'pointer',
width: '40px',
height: '40px',
})
));

Your code is correct. jQuery is not adding attributes to the element it is adding an Event Listener to the DOM. In other words it will not show up in the markup even when it is working. Try adding a console.log statement to the listener and trying it out - it should work.
On a side note there are a few best practices that might help keep your code cleaner and more maintainable.
When working with jQuery elements in JavaScript people usually use a $ to prefix variable names. In your example this would be $row.
Since you are composing nested elements it is often much cleaner to create a variable to each of the major ones and bring them together at the end. This reduces the surface area effected when you have to do refactors. In your example I might pull the $input element into it's own variable.
Inline styles and particularly styles written in JavaScript are considered bad practice. If possible you should try and add a class then style the class in your stylesheet.
Best of luck!

Related

Appending Html Classes To Elements

I asked a question yesterday (Button That When Clicked Will Display Hidden Column in HTML Table). The Name is self-explanatory however, after hours of trying new things and failing I decided to research a different approach. Here is what came up with:
A button that when clicked will append a new class to an element
By doing this, we will toggle a column's visibility by using the 'display' function in css
I have the following HTML element:
echo "<td class =\"development\" id = 'tag$i'>test1</th>";
echo "<td class =\"development\" id = 'tag$i'>test2</th>";
echo "<td class =\"development\" id = 'tag$i'>test3</th>";
$i is the row number so picture each of these <td> being wrapped inside a forloop to create a column.
With Css:
.development{
text-align:center;
padding-left:10px;
display:block;
}
.hide{
display:none;
}
So this is where I will need your help. I propose a button that when clicked will run a JavaScript function that can append the '.hide' class to the td tags.
<button onclick="addCss()">Click me</button>
I am not sure how to write the JavaScript and if I need to pass any parameters such as the id's for the <td> tags.
document.getElementById('yourId').className += ' ClassName'
//To select elements by class name.
document.getElementsByClassName('yourId')
Note: the space after the first ' for the appended class name is important.
Why? : If you have the class name "class1" and append "class2" - It will result in "class1class2"
By adding the space, it will result in "class1 class2" and be recognized as two separate classes.
<button onclick="document.getElementById('yourId').className += ' ClassName';">Click me</button>
If you want to make a better solution.
<script>
function addCss(element) {
document.getElementById(element).className += ' ClassName';
}
</script>
Then just call the function like you originally had. You could even add a parameter for the class name itself.
to override a class document.getElementById("id").className = "newclass";
to add a new class document.getElementById("id").className += " anotherclass";
function addCss(){
document.getElementById("b").className = "hide";
}
function newCss(){
document.getElementById("b").className = "show";
}
body {
font-size: 3em;
background: honeydew;
}
.hide {
display: none;
}
.show {
display: table-cell;
}
<table>
<tr>
<td id=a style="background:skyblue">A</td>
<td id=b style="background:yellowgreen">B</td>
<td id=c style="background:gold">C</td>
<td id=d style="background:orangered">D</td>
</tr>
</table>
<button onclick="addCss()">hide B cell</button>
<button onclick="newCss()">show B cell</button>
Using jQuery, you can add this in the addCss function:
$('td').addClass('hide');

change the color of text on mouseover in JS

I am very new to JS. My requirement is very simple, to change the color of Text on Mouse Over.
I have created 2 JS functions : 1st for MouseOver and 2nd for MouseOut.
Can I do it in one single JS function.
I have other Text also.
JavaScript
function highlightBG(element) {
document.getElementById('element').className='AttachOnMouseOverText';
}
function highlightOutBG(element){
document.getElementById('element').className='AttachOnMouseOutText';
}
HTML code :
<td align="center" id="element">
<img name="folder" onMouseOver="highlightBG();return true;" onMouseOut="highlightOutBG();return true;">
<br>Add Folder
</td>
You can find here the answer using pure-js as you asked :
HTML :
<div id="element" class="AttachOnMouseOutText" onMouseOver="highlightBG();return true;" onMouseOut="highlightOutBG();return true;">Hidden text</div>
CSS :
.AttachOnMouseOverText {
color: white;
}
.AttachOnMouseOutText {
color: black;
}
Javascript :
function highlightBG() {
document.getElementById('element').className='AttachOnMouseOverText';
}
function highlightOutBG(){
document.getElementById('element').className='AttachOnMouseOutText';
}
You can see here an example using CSS :hover state.
EDIT
If you want a single function to handle this, try someting like :
function highlightBG(elementName, isIn) {
if (isIn)
document.getElementById(elementName).className = 'AttachOnMouseOverText';
else
document.getElementById(elementName).className = 'AttachOnMouseOutText';
}
this is simple by using css:
selector:hover
{
color:red;
}
And you can also use jquery for this
$("selector").on( "mouseover", function() {
$( this ).css( "color", "red" );
});
If you need the hover change on a link then definitely use a :hover in CSS, it will be the most efficient way.
However if you are looking to add it to a non-link element it can cause issues in IE7 and 8. Have a look at Google Best Practices, in particular the section about :hover.
If that is the case then JS is a way to do it.
It might be easier to use jquery to do what you want, if you are using javascript you might just as well make use of jquery. Create a css class to represent the color you want to change the text to, for example
.green{
color: green;
}
Change your HTML to
<td align="center" id="element">
<img name="folder" />
<br>Add Folder
</td>
And add some jquery to add your css class when you move your mouse over 'element', for example
$("#element").mouseover(function(){
$(this).addClass("green");
});
If you want to change the color back when the mouse leaves the area, you can just remove the class again. For example
$( "#element" ).mouseleave(function() {
$(this).removeClass("green");
});
Here is the HTML (with an inline ID of "practice"):
<h1 id="practice">Hello!</h1>
Here is the vanilla JavaScript (using a generic function and a callback):
document.getElementById("practice").addEventListener("mouseover", function() {
document.getElementById("practice").style.color = "pink";
});
document.getElementById("practice").addEventListener("mouseout", function() {
document.getElementById("practice").style.color = "yellow";
});
Mousing over changes the HTML text to yellow; removing the mouse from the area returns the HTML text to black.

How to change a specific HTML string with jQuery

Here is my HTML code:
<th>
Click<br/>
<img class="magnifier" height="66" src="../Images/magnifier-zoom.png" width="75"><br/>
To Enlarge
</th>
I have a jQuery script that when clicked it toggles an enlarge class, so when someone clicks to enlarge I want to change the enlarge word to shrink would there be any simple way of doing this in jQuery?
Or do you guys think I am better off having 2 <div>'s or even <span> elements and toggle the display of each element?
There are numerous ways to do this. You could leverage pseudo-element content, do string manipulation with JavaScript, and more. In the end, the best approach is to probably just toggle the visibility of a couple nested elements:
I've placed a default "shrink" class on my td element. Within, I have a couple span elements customized with explicit data-do attributes indicating the purpose of each:
<td class="shrink">
Click to
<span data-do="enlarge">Enlarge</span>
<span data-do="shrink">Shrink</span>
<img src="..." />
</td>
We target the data-do attributes that are nested within elements that have corresponding classes, and we disable the display of these elements:
.shrink [data-do='shrink'],
.enlarge [data-do='enlarge'] {
display: none;
}
In order to toggle the class of the td element, we bind up some simple jQuery:
$("td").on("click", function () {
$(this).toggleClass("shrink enlarge");
});
Anytime a td is clicked (you can make the selector specific to a single td), we add toggle the "shrink" and "enlarge" classes. If "enlarge" was present to begin with, it is removed; otherwise it will be added. The same goes for "shrink".
Change your HTML to
<th>
<div>Click</div>
<img class="magnifier" height="66" src="../Images/magnifier-zoom.png" width="75">
<div>To Enlarge</div>
</th>
To have elements instead of text nodes.
Then you can do simple:
$('.magnifier').click(function() {
var $next = $(this).next();
$next.text($next.text() == 'To Enlarge' ? 'To Shrink' : 'To Enlarge');
})
Demo: http://jsfiddle.net/B7GDQ/
This is the direct answer to your questions, although not the best method:
$(".magnifier").on("click", function () {
if ($(this).hasClass('enlarge')) {
$(this).removeClass('enlarge');
this.parentNode.lastChild.textContent = 'To Enlarge'
}else{
$(this).addClass('enlarge');
this.parentNode.lastChild.textContent = 'To Shrink';
}
});
The ideal method would be to use pseudo elements:
Codepen
HTML:
<div class="magnifier">
Click<br/>
<img height="66" src="../Images/magnifier-zoom.png" width="75"><br/>
</div>
CSS:
.magnifier::after {
content: 'To Enlarge';
}
.magnifier.enlarge::after {
content: 'To Shrink';
}
JS:
$(".magnifier").on("click", function () {
$(this).toggleClass('enlarge');
});

Make First Ingredient never able to be deleted

I'm making an ingredients application where users insert ingredients
My application looks like this:
As you can see, the first ingredients span doesn't have a X at the end, because you must have at least one ingredient, but the rest of the ingredient spans do. I'm also using the Jquery Sortable Plugin so if you click near the outside of any of the ingredient spans, you can change the order of the ingredients. This works fine, except if you move the first ingredient span, then that span doesn't have an X at the end, even if you move it to the last spot.
So what I'm trying to do is make the first ingredient span always have no X at the end, even if switched order with another ingredient span. I tried this:
$('ingredientsCOUNT > span:first').hide(deleteButton);
but it didn't work? Any other suggestions? All help is greatly appreciated, and here's my code:
HTML (the php can just be ignored!)
<div class='formelementcontainer funky'>
<label for="ingredient">Ingredients</label>
<div id='ingredientsCOUNT' class='sortable'>
<span>
<input type="text" class='small' name="ingredient" id="ingredient" placeholder='QTY'/>
<select name='measurements'>
<option value='' name='' checked='checked'>--</option>
<?foreach ($measurements as $m):?>
<option value='<?=$m->id;?>'><?=$m->measurement;?></option>
<?endforeach;?>
</select>
<input type="text" name="ingredient" id="ingredient" placeholder='Ingredient'/>
</span>
</div>
<div class="clear"></div>
<div class='addSPAN tabover'>
<a class='float-right' id='btnAddIngredients' href='#'>Add Ingredient</a>
</div>
</div>
jQuery
(function($) {
$(document).ready(function () {
$('#btnAddIngredients').click(function () {
var num = $('#ingredientsCOUNT span').length;
var newNum = new Number(num + 1);
var deleteButton = $("<a class='float-right' style='margin:10px 2px;' href='#'><img src='<? echo base_url()."public/img/delete.png";?>' height='11' width='11' /></a>");
deleteButton.click(deleteThis);
$('#ingredientsCOUNT > span:first')
.clone()
.attr('name', 'ingredient' + newNum)
.append(deleteButton)
.appendTo('#ingredientsCOUNT')
.fadeIn();
$('ingredientsCOUNT > span:first').hide(deleteButton); //THIS IS MY SOLUTION THAT DIDN'T WORK
});
function deleteThis() {
var span = $(this).closest('span')
span.fadeOut('slow', function() { span.remove(); });
}
$( ".sortable" ).sortable(); //jQuery Sortable initialized
});
})(jQuery);
How about hiding it with CSS? The following assumes you added a class delete-button to your delete links:
#ingredientsCOUNT > span:first-child .delete-button { display: none; }
With that CSS, you can reorder the list, add or remove items, and the first delete button will never show.
Since :first-child is quirky in oldIE ( https://developer.mozilla.org/en-US/docs/CSS/:first-child#Internet_Explorer_notes ), it's possible to use the Sortable API like this:
$(".sortable").sortable({
update: function (event, ui) {
var rows = $("#ingredientsCOUNT").children("span");
rows.removeClass("first-child");
rows.first().addClass("first-child");
}
});
(there's probably a better way to utilize the event and/or ui parameters)
This way, you wouldn't have to determine which row to add a delete button to; you would always include a delete button in every row in your HTML. Then, when a sorting is done, the jQuery in the stop event (EDIT: update event) will hide the first row's delete button and show the rest (via classes).
Of course, you would need this CSS:
#ingredientsCOUNT > span.first-child a.delete-button {
display: none;
}
And to add a delete-button class to your delete buttons <a>
EDIT:
I changed the Sortable method from stop to update so that it only runs the code when the sorting arrangement has actually changed, after the sorting is done.

bootstrap "tooltip" and "popover" add extra size in table

Note:
Depending on you Bootstrap version (prior to 3.3 or not), you may need a different answer.
Pay attention to the notes.
When I activate tooltips (hover over the cell) or popovers in this code, size of table is increasing. How can I avoid this?
Here emptyRow - function to generate tr with 100
<html>
<head>
<title></title>
<script type="text/javascript" language="javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<link type="text/css" rel="stylesheet" href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css">
<script type="text/javascript" language="javascript" src="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.2.1/bootstrap.min.js"></script>
<style>
#matrix td {
width: 10px;
height: 10px;
border: 1px solid gray;
padding: 0px;
}
</style>
<script>
function emptyRow() {
str = '<tr>'
for (j = 0; j < 100; j++) {
str += '<td rel="tooltip" data-original-title="text"></td>'
}
str += '</tr>'
return str
}
$(document).ready(function () {
$("#matrix tr:last").after(emptyRow())
$("[rel=tooltip]").tooltip();
});
</script>
</head>
<body style="margin-top: 40px;">
<table id="matrix">
<tr>
</tr>
</table>
</body>
</html>
thank in advice!
Note: Solution for Bootstrap 3.3+
Simple Solution
In the .tooltip() call, set the container option to body:
$(function () {
$('[data-toggle="tooltip"]').tooltip({
container : 'body'
});
});
Alternatively you can do the same by using the data-container attribute:
<p data-toggle="tooltip" data-placement="left" data-container="body" title="hi">some text</p>
Why does this work?
This solves the problem because by default, the tooltip has display: block and the element is inserted in the place it was called from. Due to the display: block, it affects the page flow in some cases, i.e pushing other elements down.
By setting the container to the body element, the tooltip is appended to the body instead of where it was called from, so it doesn't affect other elements because there is nothing to "push down".
Bootstrap Tooltips Documentation
Note: Solution for Bootstrap 3.0 ~ 3.2
You need to create an element inside a td and apply a tooltip to it, like this, because a tooltip itself is a div, and when it is placed after a td element it brakes table layout.
This problem was introduced with the latest release of Bootstrap. There are ongoing discussions about fixes on GitHub here. Hopefully the next version includes the fixed files.
Note: Solution for Bootstrap 3.3+
If you want to avoid to break the table when applying a tooltip to a <td> element, you could use the following code:
$(function () {
$("body").tooltip({
selector: '[data-toggle="tooltip"]',
container: 'body'
});
})
You html could look like this:
<td data-toggle="tooltip" title="Your tooltip data">
Table Cell Content
</td>
This even works with dynamically loaded content. For example in use with datatables
I would like to add some precision to the accepted answer, I decided to use the answer format for readibility.
Note: Solution for Bootstrap 3.0 ~ 3.2
Right now, wrapping your tooltip in a div is the solution, but it will need some modifications if you want your whole <td> to show the tooltip (because of Bootstrap CSS). A simple way to do it is to transfert <td>'s padding to wrapper :
HTML
<table class="table table-hover table-bordered table-striped">
<tr>
<td>
<div class="show-tooltip" title="Tooltip content">Cell content</div>
</td>
</tr>
</table>
JS (jQuery)
$('.show-tooltip').each(function(e) {
var p = $(this).parent();
if(p.is('td')) {
/* if your tooltip is on a <td>, transfer <td>'s padding to wrapper */
$(this).css('padding', p.css('padding'));
p.css('padding', '0 0');
}
$(this).tooltip({
toggle: 'toolip',
placement: 'bottom'
});
});
If you are using datatable for table then it will be use full
$('#TableId').DataTable({
"drawCallback": function (settings) {
debugger;
$('[data-toggle="tooltip"]').tooltip({
container: 'body'
});
}
});
You should initialize Tooltip inside datatable function fnDrawCallback
"fnDrawCallback": function (data, type, full, meta) {
$('[data-toggle="tooltip"]').tooltip({ placement: 'right', title: 'heyo', container: 'body', html: true });
},
And define your column as below
{
targets: 2,
'render': function (data, type, full, meta) {
var htmlBuilder = "<b>" + data + "</b><hr/><p>Description: <br/>" + full["longDescrioption"] + "</p>";
return "<a href='#' class='Name'>" + (data.length > 50 ? data.substr(0, 50) + '…' : data) + "</a>" +
"<sup data-toggle='tooltip' data-original-title=" + htmlBuilder + ">"+
"<i class='ic-open-in-new ic' style='font-size:12px;margintop:-3px;'></i></sup>";
}
},
If you're using bootstrap directives for AngularJS, use tooltip-append-to-body attribute.
<td ng-repeat="column in row.columns" uib-tooltip="{{ ctrl.viewModel.leanings.tooltip }}" tooltip-append-to-body="true"></td>

Categories