In order to export a view to an excel file I use this but the problem is that I can't export the last line generated by sum attributes:
if (children) {
// find only rows with data
view.$el.find('.o_list_view > tbody > tr[data-id]:has(.o_list_record_selector input:checkbox:checked)')
.each(function () {
var $row = $(this);
var export_row = [];
$.each(export_columns_keys, function () {
var $cell = $row.find('td[data-field="' + this + '"]')
var $cellcheckbox = $cell.find('.o_checkbox input:checkbox');
if ($cellcheckbox.length) {
export_row.push(
$cellcheckbox.is(":checked")
? _t("True") : _t("False")
);
}
else {
var text = $cell.text().trim();
export_row.push(text);
}
});
export_rows.push(export_row);
});
}
how can I add it ? is there a way?
Shouldn't var export_row = []; be var export_rows = []; ? (Note the final s)
I am a beginner at working with JSON and have not used it much, how do I split the genre for a tv show into individual genres and add any new genres to the options of the drop down? I want to split the genres that have a '|' and then add them to the 2nd drop-down select as options. How do I also set "Comedy" as the default option? Thanks in advance.
$(function () {
$("#chooseByGenre").click(function () {
var text = $("#yourGenre").val();
text = text.replace(/\|, " ");
var edg = text.split("");
$("#genreSelection").html("");
for (i = 0; i < edg.length; i++) {
if (edg[i] < "a" || edg[i] > "z") {
$("#genreSelection").append("<br />");
}
else {
$("#genreSelection").append('<img src="sign' + edg[i] + '.g" />');
}
}
});
code for default option:
var JSON_Response;
$(document).ready(function () {
$.getJSON('Show.json', function (data) {
JSON_Response = data;
var mySelect = document.getElementById("selShow");
for (i = 0; i < JSON_Response.shows.length; i++) {
var myOption = document.createElement("option");
myOption.text = JSON_Response.shows[i].Title;
myOption.value = i;
try {
mySelect.add(myOption, mySelect.options[null]);
}
catch (e) {
mySelect.add(myOption, null);
}
} //end for
var mySelect2 = document.getElementById("selGenre");
for (i = 0; i < JSON_Response.shows.length; i++) {
var myOption2 = document.createElement("option");
myOption2.text = JSON_Response.shows[i].Genre;
myOption2.value = i;
try {
mySelect2.add(myOption2, mySelect2.options[null]);
}
catch (e) {
mySelect2.add(myOption, null);
}
} //end for
}); //end getJSON
probably you can try like this? (haven't tested yet):
...
try {
if ( myOption2.text == 'comedy') {
myOption2.setAttribute("selected", "selected");
}
mySelect2.add(myOption2, mySelect2.options[null]);
}
...
I am working on this demo. How can I add each selected row as an array into the data [] so that it looks like this:
[{"Cell phone":"BlackBerry Bold 9650","Rating":"2/5","Location":"UK"},
{"Cell phone":" Samsung Galaxy","Rating":"3/5","Location":"US"}]
Here is the code I have:
var data = [];
function myfunc(ele) {
var values = new Array();
$.each($("input[name='case[]']:checked").closest("td").siblings("td"),
function () {
values.push($(this).text());
});
alert("val---" + values.join (", "));
}
$(document).ready(function() {
$("input.case").click(myfunc);
});
check if this works,
here is the fiddle demo
var data = [];
function myfunc(ele) {
var values = [];
var keys = [];
$.each($("input[name='case[]']:checked").closest("table").find('th'),
function () {
keys.push($(this).text());
});
keys.shift(); // to remove the first key
var len = keys.length, obj={}, ctr=0;
$.each($("input[name='case[]']:checked").closest("td").siblings("td"),
function () {
obj[keys[ctr]]=$(this).text();
ctr++;
if(ctr==len){
values.push(obj);
obj={};
ctr=0;
}
});
alert("val---" + JSON.stringify(values));
}
$(document).ready(function() {
$("input.case").click(myfunc);
});
http://jsfiddle.net/ugdas2em/
Try this:
var data = {};
function myfunc(ele) {
//var values = new Array();
var k = 0;
var j = 0;
data[k] = {};
$.each($("input[name='case[]']:checked").closest("td").siblings("td"),
function () {
if(j==3)
{
k = k+1;
data[k] = {};
j = 0;
}
//values.push($(this).text());
data[k][j] = $(this).text();
j=j+1;
});
console.debug(data);
//alert("val---" + values.join (", "));
}
$(document).ready(function() {
$("input.case").click(myfunc);
});
Note: If you want then you can use [] with data variable in place of {} in my code. You need to replace at three place. Thanks.
In the following code, I have some divs with <a> tags, each containing a href of /User.aspx?ID=[some ID]. I wish to click the Delete <a> tag under the parent of the parent of the parent of any divs with duplicate ID's in the href.
Here is my code:
var z = 0;
var info = {};
$("a:contains('Delete')").each(function() {
z++;
var x = $(this).parent().parent().parent().find("span.UserLink a").attr("href");
var id = x.replace("/User.aspx?ID=", "");
info[z] = id;
console.log(info[z]);
});
var uniqueIds = {};
$.each(info, function(i, el){
if($.inArray(el, uniqueIds) === -1) { uniqueIds.push(el) }
else { $("html").find("span.UserLink a[href='/User.aspx?ID='"+info[i]+"']").parent().parent().parent().find("a:contains('Delete')").click() }
});
Use arrays, not objects
Maybe just a typo, I think you wanted to use arrays for info and uniqueIds
var info = [];
var uniqueIds = [];
jQuery.each already provides an index
You don't need z
$("a:contains('Delete')").each(function(index) {
var x = $(this).parent().parent().parent().find("span.UserLink a").attr("href");
var id = x.replace("/User.aspx?ID=", "");
info[index] = id;
console.log(info[z]);
});
Use meaningful names
x and info aren't very good names, you could try (for example) userLinkHref and foundIds
You could store the delete button in the first loop and use it in the second loop
var foundDeleteLinks = [];
$("a:contains('Delete')").each(function() {
var $deleteLink = $(this);
var userLinkHref = $deleteLink.parent().parent().parent().find("span.UserLink a").attr("href");
var id = userLinkHref.replace("/User.aspx?ID=", "");
foundDeleteLinks.push({id:id,$deleteLink:$deleteLink});
console.log(id);
});
var uniqueIds = [];
$.each(foundDeleteLinks, function(i, deleteLink){
var id = deleteLink.id;
if($.inArray(id, uniqueIds) === -1) { uniqueIds.push(id) }
else {
deleteLink.$deleteLink.click();
}
});
You may be able to do it in one loop
var foundIds = [];
$("a:contains('Delete')").each(function() {
var $deleteLink = $(this);
var userLinkHref = $deleteLink.parent().parent().parent().find("span.UserLink a").attr("href");
var id = userLinkHref.replace("/User.aspx?ID=", "");
if($.inArray(id, foundIds) === -1) { foundIds.push(id) }
else { $deleteLink.click(); }
});
I hope that helps enough to find your problems.
I have the the following code
<b class="xyzxterms" style="cursor: default; ">bryant keil bio</b>
How would I replace the b tag to a h1 tag but keep all other attributes and information?
Here's one way you could do it with jQuery:
var attrs = { };
$.each($("b")[0].attributes, function(idx, attr) {
attrs[attr.nodeName] = attr.nodeValue;
});
$("b").replaceWith(function () {
return $("<h1 />", attrs).append($(this).contents());
});
Example: http://jsfiddle.net/yapHk/
Update, here's a plugin:
(function($) {
$.fn.changeElementType = function(newType) {
var attrs = {};
$.each(this[0].attributes, function(idx, attr) {
attrs[attr.nodeName] = attr.nodeValue;
});
this.replaceWith(function() {
return $("<" + newType + "/>", attrs).append($(this).contents());
});
};
})(jQuery);
Example: http://jsfiddle.net/mmNNJ/
Not sure about jQuery. With plain JavaScript you could do:
var new_element = document.createElement('h1'),
old_attributes = element.attributes,
new_attributes = new_element.attributes;
// copy attributes
for(var i = 0, len = old_attributes.length; i < len; i++) {
new_attributes.setNamedItem(old_attributes.item(i).cloneNode());
}
// copy child nodes
do {
new_element.appendChild(element.firstChild);
}
while(element.firstChild);
// replace element
element.parentNode.replaceChild(new_element, element);
DEMO
Not sure how cross-browser compatible this is though.
A variation could be:
for(var i = 0, len = old_attributes.length; i < len; i++) {
new_element.setAttribute(old_attributes[i].name, old_attributes[i].value);
}
For more information see Node.attributes [MDN].
#jakov and #Andrew Whitaker
Here is a further improvement so it can handle multiple elements at once.
$.fn.changeElementType = function(newType) {
var newElements = [];
$(this).each(function() {
var attrs = {};
$.each(this.attributes, function(idx, attr) {
attrs[attr.nodeName] = attr.nodeValue;
});
var newElement = $("<" + newType + "/>", attrs).append($(this).contents());
$(this).replaceWith(newElement);
newElements.push(newElement);
});
return $(newElements);
};
#Jazzbo's answer returned a jQuery object containing an array of jQuery objects, which wasn't chainable. I've changed it so that it returns an object more similar to what $.each would have returned:
$.fn.changeElementType = function (newType) {
var newElements,
attrs,
newElement;
this.each(function () {
attrs = {};
$.each(this.attributes, function () {
attrs[this.nodeName] = this.nodeValue;
});
newElement = $("<" + newType + "/>", attrs).append($(this).contents());
$(this).replaceWith(newElement);
if (!newElements) {
newElements = newElement;
} else {
$.merge(newElements, newElement);
}
});
return $(newElements);
};
(Also did some code cleanup so it passes jslint.)
Only way I can think of is to copy everything over manually: example jsfiddle
HTML
<b class="xyzxterms" style="cursor: default; ">bryant keil bio</b>
Jquery/Javascript
$(document).ready(function() {
var me = $("b");
var newMe = $("<h1>");
for(var i=0; i<me[0].attributes.length; i++) {
var myAttr = me[0].attributes[i].nodeName;
var myAttrVal = me[0].attributes[i].nodeValue;
newMe.attr(myAttr, myAttrVal);
}
newMe.html(me.html());
me.replaceWith(newMe);
});
#Andrew Whitaker: I propose this change:
$.fn.changeElementType = function(newType) {
var attrs = {};
$.each(this[0].attributes, function(idx, attr) {
attrs[attr.nodeName] = attr.nodeValue;
});
var newelement = $("<" + newType + "/>", attrs).append($(this).contents());
this.replaceWith(newelement);
return newelement;
};
Then you can do things like: $('<div>blah</div>').changeElementType('pre').addClass('myclass');
I like the idea of #AndrewWhitaker and others, to use a jQuery plugin -- to add the changeElementType() method. But a plugin is like a blackbox, no mater about the code, if it is litle and works fine... So, performance is required, and is most important than code.
"Pure javascript" have better performance than jQuery: I think that #FelixKling's code have better performance than #AndrewWhitaker's and others.
Here a "pure Javavascript" (and "pure DOM") code, encapsulated into a jQuery plugin:
(function($) { // #FelixKling's code
$.fn.changeElementType = function(newType) {
for (var k=0;k<this.length; k++) {
var e = this[k];
var new_element = document.createElement(newType),
old_attributes = e.attributes,
new_attributes = new_element.attributes,
child = e.firstChild;
for(var i = 0, len = old_attributes.length; i < len; i++) {
new_attributes.setNamedItem(old_attributes.item(i).cloneNode());
}
do {
new_element.appendChild(e.firstChild);
}
while(e.firstChild);
e.parentNode.replaceChild(new_element, e);
}
return this; // for chain... $(this)? not working with multiple
}
})(jQuery);
Here is a method I use to replace html tags in jquery:
// Iterate over each element and replace the tag while maintaining attributes
$('b.xyzxterms').each(function() {
// Create a new element and assign it attributes from the current element
var NewElement = $("<h1 />");
$.each(this.attributes, function(i, attrib){
$(NewElement).attr(attrib.name, attrib.value);
});
// Replace the current element with the new one and carry over the contents
$(this).replaceWith(function () {
return $(NewElement).append($(this).contents());
});
});
With jQuery without iterating over attributes:
The replaceElem method below accepts old Tag, new Tag and context and executes the replacement successfully:
replaceElem('h2', 'h1', '#test');
function replaceElem(oldElem, newElem, ctx) {
oldElems = $(oldElem, ctx);
//
$.each(oldElems, function(idx, el) {
var outerHTML, newOuterHTML, regexOpeningTag, regexClosingTag, tagName;
// create RegExp dynamically for opening and closing tags
tagName = $(el).get(0).tagName;
regexOpeningTag = new RegExp('^<' + tagName, 'i');
regexClosingTag = new RegExp(tagName + '>$', 'i');
// fetch the outer elem with vanilla JS,
outerHTML = el.outerHTML;
// start replacing opening tag
newOuterHTML = outerHTML.replace(regexOpeningTag, '<' + newElem);
// continue replacing closing tag
newOuterHTML = newOuterHTML.replace(regexClosingTag, newElem + '>');
// replace the old elem with the new elem-string
$(el).replaceWith(newOuterHTML);
});
}
h1 {
color: white;
background-color: blue;
position: relative;
}
h1:before {
content: 'this is h1';
position: absolute;
top: 0;
left: 50%;
font-size: 5px;
background-color: black;
color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="test">
<h2>Foo</h2>
<h2>Bar</h2>
</div>
Good Luck...
Javascript solution
Copy the attributes of old element to the new element
const $oldElem = document.querySelector('.old')
const $newElem = document.createElement('div')
Array.from($oldElem.attributes).map(a => {
$newElem.setAttribute(a.name, a.value)
})
Replace the old element with the new element
$oldElem.parentNode.replaceChild($newElem, $oldElem)
Here is my version. It's basically #fiskhandlarn's version, but instead of constructing a new jQuery object, it simply overwrites the old elements with the newly created ones, so no merging is necessary.
Demo: http://jsfiddle.net/0qa7wL1b/
$.fn.changeElementType = function( newType ){
var $this = this;
this.each( function( index ){
var atts = {};
$.each( this.attributes, function(){
atts[ this.name ] = this.value;
});
var $old = $(this);
var $new = $('<'+ newType +'/>', atts ).append( $old.contents() );
$old.replaceWith( $new );
$this[ index ] = $new[0];
});
return this;
};