I have 4 tables generated dynamically. There is two divs in each cell (td). All the divs are droppable. I dont know why but only the 2nd div accepts the draggable, the first one reverts it. There is no different between the two divs (exepts one has a "dotted" class).
Here is the jsbin:
http://jsbin.com/OMIbOGU/22/edit
JS
$("document").ready(function(){
function init(){
var table = $("<table></table>");
$("body").append(table);
for(var i=0 ;i < 9; i++){
var row = $("<tr></tr>");
var cell = $("<td></td>");
for(var j = 0;j<2;j++){
var slot = $("<div></div>").addClass('slot');
slot.droppable({
accept: ".unassigned"
});
if (j!==1)
slot.addClass("dotted");
cell.append(slot);
}
row.append(cell);
table.append(row);
}
$(".unassigned").draggable({
revert: "invalid",
snap: "td div"
});
}
for(var i = 0 ; i<4;i++)
init();
});
if you add
tolerance: 'touch'
to the droppable it works. Which points to it being more of a css issue than one with the script.
Updated JS BIN
Related
I am using pdfMake to generate table reports. Some of the reports are very wide and dont fit on a standard page width, even in landscape mode. Currently, pdfMake is cutting off the table content when it overflows past the page margin.
I would like to page break the table when it is too wide, much like when the rows overflow to the next page.
Is this possible using pdfMake?
Can using pageBreakBefore callback function help for this?
Thank you
Yes, this is possible with pdfMake, even though not currently a feature.
To achieve this, you can just break overflowing columns into another table. We can put all the tables in an array, then just set them in the docDefinition as follows.
Any common attributes you want in the tables can be defined in the Template constructor.
for (var i = 0; i < tables.length;i++) {
docDefinition.content[i] = new Template();
docDefinition.content[i].table.body = tables[i];
docDefinition.content[i].table.widths = widths[i];
if (i > 0) {
docDefinition.content[i].pageBreak = 'before';
}
}
function Template(){
this.table = {
dontBreakRows: true
};
//zebra stripes layout
this.layout = {
fillColor: function (row, node, col) {
return (row % 2 === 0) ? '#CCCCCC' : null;
}
}
}
How do we determine if a column will overflow? We have two options:
If you are using bootstrap datatables, you can use the "width" attribute in the html.
pdfmake calculates the actual width, but you may have to dig around in pdfmake.js.
Then, just loop through, adding widths until you exceed your limit (my limit was for 8pt font). You can do this for THs then save those column splits and use those for the TDs.
If the final page is just barely overflowing, we don't want the final page to have just one column, we want each page to have roughly the same width. We calculate the number of pages needed, then find the desired break point from there. To link the pages together more easily, you can add a row number column at the beginning of each table.
var colSplits = [];
var tables = new Array();
function parseTHs(colSplits, tables) {
var colSum = 0;
var pageSize = 1120-7*rows.toString().length;
var paddingDiff = 11.9;
var columns = 0;
var prevSum;
var i = 0;
var width = $(".dataTables_scrollHeadInner > table").width();
var pages = Math.ceil(width/pageSize);
console.log("pages: "+pages);
var desiredBreakPoint = width/pages;
console.log("spread: "+desiredBreakPoint);
var limit = pageSize;
var row = ['#'];
var percent = '%';
widths.push(percent);
$(".dataTables_scrollHeadInner > table > thead > tr:first > th").each(function() {
prevSum = colSum;
colSum += $(this).outerWidth()-paddingDiff;
//if adding column brings us farther away from the desiredBreakPoint than before, kick it to next table
if (colSum > limit || desiredBreakPoint-colSum > desiredBreakPoint-prevSum) {
tables[i] = [row];
row = ['#'];
widths.push(percent);
colSplits.push(columns);
i++;
desiredBreakPoint += width/pages;
limit = prevSum+pageSize;
}
row.push({text: $(this).text(), style:'header'});
widths.push(percent);
columns++;
});
//add the final set of columns
tables[i] = [row];
}
function parseTDs(colSplits, tables) {
var currentRow = 0;
$("#"+tableId+" > tbody > tr").each(function() {
var i = 0;
var row = [currentRow+1];
var currentColumn = 0;
var split = colSplits[i];
$(this).find("td").each(function() {
if (currentColumn === split) {
tables[i].push(row);
row = [currentRow+1];
i++;
split = colSplits[i];
}
row.push({text: $(this).text()});
currentColumn++;
});
//add the final set of columns
tables[i].push(row);
currentRow++;
});
}
parseTHs(colSplits, tables);
parseTDs(colSplits, tables);
Note: If you want the columns to fill all the available page, there's a good implementation for that at this link.
I just added '%' for the widths and added that code to pdfmake.js.
Hope this helps!
Just add dontBreakRows property in your table object like this
table: {
dontBreakRows: true,
widths: [30,75,48,48,48,48,48,115],
body: []
}
Also, you can make the page wider and change the page orientation as landscape.
pageSize: "A2",
pageOrientation: "landscape",
I have a sortable list that has a corresponding data array, I need to change the order of the array when the list is reordered. I use this code
o.dom.$editor.find('.sortable').sortable({
start: function(event, ui) {
var start_pos = ui.item.index();
ui.item.data('startIndex', start_pos); // store original index
},
change: function(event, ui) {
var start_pos = ui.item.data('startIndex'); // get original index
var index = ui.placeholder.index() - 1; // get new index
console.log(start_pos, index); // log start and end positions for debugging
ui.item.data('startIndex', index); // store new index
}
});
As an example, let's say I have this list:
A
B
C
I hold list item A and drag it down to the bottom, the change event fires twice, first swapping item A with item B, then A with C, the console shows:
0 1
1 2
And it's correct. Now (WITHOUT releasing the mouse from the previous drag), I drag back item A to the top, again the change event fires twice, swapping A with C, then A with B, console shows:
2 1
1 0
All good.
Now if I release the mouse, and start dragging item B to the top, the change event fires once, swapping B with A, but console shows:
1 -1
Which is wrong. What's going on here? I've been trying to figure this out for hours.
jsfiddle: https://jsfiddle.net/4dtdk2qo/1/
Problem is in var index = ui.placeholder.index() - 1; line.
When you move item from up to down , index for ui.placeholder.index() starts from 1
when you move item from down to up , index for ui.placeholder.index() starts from 0
I have changed logic of getting index.
$(function(){
$('.sortable').sortable({
start: function(event, ui) {
var start_pos = ui.item.index();
ui.item.data('startIndex', start_pos);
},
change: function(event, ui) {
var start_pos = ui.item.data('startIndex');
var index = ui.placeholder.index();
index = (start_pos > index) ? index : index - 1;
$("#output").append(start_pos + ' ' + index + '<br>');
ui.item.data('startIndex', index);
}
});
})
li{
display: block;
background: lightgreen;
margin:20px 0;
}
#output{
width:100%;
min-height: 20px;
background: lightgray;
}
<link href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<ul class='sortable'>
<li>A</li>
<li>B</li>
<li>C</li>
</ul>
<div id="output">
I want to get this:
But I need to create the HTML dynamically because it's loaded via AJAX from an external ressource.
I already asked this question here (JQM: Dynamic nested collapsibles - $(collapsible).collapsible() & $(collapsible).trigger('create')) but I got it completly wrong with lists and collapsibles, so I figured a new question would be better.
Here is what I got so far:
function loadTipps() {
console.log("Lade Tipps..");
var categoriesURL = tippsURL+"?type=kategorien&callback=?"; // url for the categories
$.getJSON(categoriesURL,function(data) {
console.log("Lade Kategorien..");
var DIV_tipps_komplett = $("#tipps_komplett");
$.each(data, function(key,value){
var kategorie_ID = value.id;
var kategorie_NAME = value.name;
var collapsible_HTML = $('<div data-role="collapsible"></div>');
var kategorie_Ueberschrift_HTML = $('<h3>'+kategorie_NAME+'</h3>');
var tipps_kategorie_HTML = $('<div id="tipps_kategorie'+kategorie_ID+'" data-role="collapsible-set"></div>');
var tippURL = tippsURL+"?type=tipp&kat_id="+value.id+"&callback=?"; // url for the tipps of the current category
$.getJSON(tippURL,function(data2) {
$.each(data2, function(key2,value2){
var tipp_Ueberschrift_Text_HTML = '<div data-role="collapsible"><b>'+value2.name+'</b><p>'+value2.text+'</p><br></div>';
tipps_kategorie_HTML.append(tipp_Ueberschrift_Text_HTML);
}); //<--each
});//<--getJSON
collapsible_HTML.append(kategorie_Ueberschrift_HTML);
collapsible_HTML.append(tipps_kategorie_HTML);
DIV_tipps_komplett.append(collapsible_HTML);
});//<--each
DIV_tipps_komplett.trigger('create');
});//<--getJSON
}
This results in:
As you can see, the items in the first collapsible set are not in another collapsible set. Any ideas why?
Try changing the line:
var tipp_Ueberschrift_Text_HTML = '<div data-role="collapsible"><b>'+value2.name+'</b><p>'+value2.text+'</p><br></div>';
to
var tipp_Ueberschrift_Text_HTML = '<div data-role="collapsible"><h3>'+value2.name+'</h3><p>'+value2.text+'</p><br></div>';
The Collapsible needs the <h3> element instead of <b> to render.
Here is a demo of your exact code with the AJAX calls removed: http://jsfiddle.net/ezanker/RkLuV/
By the way, this is pretty much the answer I gave you here: collapsible list with collapsed items in jqm, it would probably have been better to continue the conversation there.
i wanna ask how to change title in
name
so i want to make link name copy to title automatic
so if i make this code
title link
to
title link
how to do that in php or javascript
i know some in php
but need to make all words in link at database or make for every link variable $
can some one help me in that?
I'd suggest:
function textToTitle(elem, attr) {
if (!elem || !attr) {
// if function's called without an element/node,
// or without a string (an attribute such as 'title',
// 'data-customAttribute', etc...) then returns false and quits
return false;
}
else {
// if elem is a node use that node, otherwise assume it's a
// a string containing the id of an element, search for that element
// and use that
elem = elem.nodeType == 1 ? elem : document.getElementById(elem);
// gets the text of the element (innerText for IE)
var text = elem.textContent || elem.innerText;
// sets the attribute
elem.setAttribute(attr, text);
}
}
var link = document.getElementsByTagName('a');
for (var i = 0, len = link.length; i < len; i++) {
textToTitle(link[i], 'title');
}
JS Fiddle demo.
And since it seems traditional to offer a concise jQuery option:
$('a').attr('title', function() { return $(this).text(); });
JS Fiddle demo.
If you don't want to use a library:
var allLinks = document.getElementsByTagName('a');
for(var i = 0; i < allLinks.length; i++){
allLinks[i].title = allLinks[i].innerHTML;
}
Since you wanted to do all this to one element on the page, consider using something like this:
var allLinks = document.getElementById('myelement').getElementsByTagName('a'); // gets all the link elements out of #myelement
for ( int i = 0; i < allLinks.length; i++ ){
allLinks[i].title = allLinks[i].innerHTML;
}
Actually, this is roughly the same as before but we are changing the input elements.
Or, assuming you use jQuery, you could do something like this:
$('a').each(function(){ // runs through each link element on the page
$(this).attr('title', $(this).html()); // and changes the title to the text within itself ($(this).html())
});
In JQuery you can change an attribute by knowing the current tag and using the .attr() feature. Something like $('a').attr('title', 'new_title'); http://api.jquery.com/attr/
I am creating a JQuery Mobile application that has a listview. I am populating that listview with the results of a web service. Because of this, the items in the list view are being populated as shown here:
$.each(results, function (i, result) {
var s = "<li><h2 style='padding-left:40px;'>" + result.title + "</h2><p style='padding-left:40px;'>";
s += result.subTitle;
s += "</p><span class='ul-li-count'>" + result.count + "</span></li>";
$("#resultListView").append(s);
});
$("#resultListView").listview("refresh");
My listview is being populated correctly. The value for the count bubble is showing. However, the UI does not render the bubble. Is there a way to dynamically build a result set with count bubbles in a list view? If so, how?
Thank you!
Your way should work. The only thing I can think of is that the HTML is not valid.
Anyway, I created a simple version to show that it's possible. http://jsfiddle.net/kiliman/HDUqp/
Basically, just build up the HTML for <li/> and append to the list, then call .listview('refresh')
$('#page1').bind('pageinit', function(e, data) {
var n = 0;
$('#addResult').click(function(e) {
var $list = $('#resultListView');
n++;
$('<li/>')
.append($('<h2>', { text: 'Title ' + n }))
.append($('<p>', { text: 'SubTitle ' + n }))
.append($('<span />', { text: n, class: 'ui-li-count'}))
.appendTo($list);
$list.listview('refresh');
});
});