Related
I created a Custom Widget in Dojo
return declare("DrawTools", [_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], {
templateString: template,
layers: [],
constructor: function (featureLayerArr) {
},
postCreate: function () {
},
startup: function () {
var menu = new DropDownMenu({ style: "display: none;" });
var menuItem1 = new MenuItem({
label: "Save",
iconClass: "dijitEditorIcon dijitEditorIconSave",
onClick: function () { alert('save'); }
});
menu.addChild(menuItem1);
var menuItem2 = new MenuItem({
label: "Cut",
iconClass: "dijitEditorIcon dijitEditorIconCut",
onClick: function () { alert('cut'); }
});
menu.addChild(menuItem2);
menu.startup();
var button = new DropDownButton({
label: "hello!",
name: "programmatic2",
dropDown: menu,
id: "progButton"
}, this.drawToolsMenuNode).startup();
},
startMenu: function () {
}
});
Wdiget template is as follows
<div>
<div data-dojo-attach-point="drawToolsMenuNode"></div>
</div>
I am instantiating Widget in another Custom Widget as follows
var drawTools = new DrawTools(this.allLayersArr);
drawTools.placeAt(this.drawToolsNode);
drawTools.startMenu();
startup method for DrawTools widget is not getting called.
Need help in this regard.
Offical definition from dojo
startup():
Probably the second-most important method in the Dijit lifecycle is the startup method. This method is designed to handle processing after any DOM fragments have been actually added to the document; it is not fired until after any potential child widgets have been created and started as well. This is especially useful for composite widgets and layout widgets.
When instantiating a widget programmatically, always call the widget's startup() method after placing it in the document. It's a common error to create widgets programmatically and then forget to call startup, leaving you scratching your head as to why your widget isn't showing up properly.
So as Kirill mentioned, you need to call the startup method.
The alternative solution would be moving widget instantiation logic from ::startup() to ::postCreate(), since ::postCreate() will be called for sure.
I'm very new to Datatables plugin and i'm using it for my small project. I have the following problem like this:
+ I want to create a table and each row have a link to pop up a modal for editing.
Currently my datatables implementation as follow:
$(document).ready(function () {
$('#dtTable').DataTable({
serverSide: false,
processing: true,
deferRender: true,
ajax: {
type: 'POST',
url: '#Url.Action("GetClasses", "CLASSes")',
dataSrc: ""
},
columns: [
{ data: 'CLASSID' },
{ data: 'CLASSCODE' },
{ data: 'CLASSNAME' },
{
orderable: false,
searchable: false,
render: function (data, type, full, meta) {
debugger;
var data = full.CLASSID;
return 'Action';
}
}
]
});
})
The problem is that when ever i click on the Action link the modal will appear and then disappear instantly, place a debugger at the render section it's seemed that this section call twice and i don't know why?
So please help me to achieve this, each row has its link to pop up a modal and when click on it.
Thanks you guys very much
jQuery DataTables plug-in indeed calls render multiple times: for data type detection, display, sorting, etc.
Use the following code to produce content for display only:
render: function (data, type, full, meta) {
if(type === 'display'){
data = 'Action';
}
return data;
}
Regarding modal dialogs, most likely there is a problem somewhere else in your code that makes the modal dialog disappear.
I have an Ajax enabled WebGrid and inside this grid I have a column which generates an ActionLink, this ActionLink has a "class" added so I can catch it with jQuery and open a Dialog based on the URL passed -> this URL is a call to a method which returns a PartialView.
This is working for all buttons on first page, as soon as I change the paging the script is not called and my partial view is displayed without a layout. So the action is executed but not through javascript (where I put return false; so I don't get double postbacks).
Code:
#Code
Dim grid As New WebGrid(Model,
rowsPerPage:=10,
canSort:=True,
canPage:=True,
ajaxUpdateContainerId:="ajaxGridClientBookingWL",
fieldNamePrefix:="ajaxGridClientBookingWL",
pageFieldName:="ajaxGridClientBookingWL")
End Code
<div id="ajaxGridClientBookingWL">
<script type="text/javascript">
$(document).ready(function () {
$(".popup-button").click(function () {
//debugger;
var href = $(".popup-button").attr('href');
InitializeDialog($("#modPop"), href);
$("#modPop").dialog("open");
return false;
});
function InitializeDialog($element, href) {
$element.dialog({
autoOpen: false,
width: 400,
resizable: true,
draggable: true,
title: "Department Operation",
modal: true,
closeText: '[Zapri]',
dialogClass: 'no-close normalpopup-dialog',
closeOnEscape: true,
open: function (event, ui) {
$element.load(href);
},
close: function () {
$(this).dialog('close');
}
});
}
});
</script>
<div id="modPop">
</div>
<table cellpadding="3px">
<tr>
<td>#grid.GetHtml(tableStyle:="gridTable", headerStyle:="gridHeader", rowStyle:="gridRowStyle", alternatingRowStyle:="gridAlternatingRow",
columns:=grid.Columns(
grid.Column(header:="Datum", columnName:="DateInserted", canSort:=True, format:=##<text>#NiRISHelpers.SpanDateToShort(item.DateInserted)</text>),
grid.Column(header:="", format:=##<text>#Html.ActionLink("Izberi", "KomitentBookingWLPreveril", "Pregled", New With {.area = "Komitent", .ID = item.IDrec}, New With {.class = "popup-button"})</text>)
))</td>
</tr>
</table>
</div>
You can see I set a debugger which catches my action if on first page, it does not when I page this grid.
I put everything inside the div which is designated as ajaxUpdateContainerId, tried to put it outside of it but nothing seems to work.
The partial view is just a simple #Html.DisplayFor(....).
Edit - solution:
As per #JoeJoe87577 accepted answer below, here is my new code (the rest is the same as above only scripts and grid.column are changed):
<script type="text/javascript">
function readyTheButton() {
var href = $(".popup-button").attr('href');
InitializeDialog($("#modPop"), href);
$("#modPop").dialog("open");
return false;
}
function InitializeDialog($element, href) {
$element.dialog({
autoOpen: false,
width: 400,
resizable: true,
draggable: true,
title: "Department Operation",
modal: true,
closeText: '[Zapri]',
dialogClass: 'no-close normalpopup-dialog',
closeOnEscape: true,
open: function (event, ui) {
$element.load(href);
},
close: function () {
$(this).dialog('close');
}
});
}
</script>
And the grid.Column:
grid.Column(
header:="",
format:=##<text>#Ajax.ActionLink(
"Izberi",
"KomitentBookingWLPreveril",
"Pregled",
New With {.area = "Komitent", .ID = item.IDrec},
New AjaxOptions With {
.HttpMethod = "GET",
.InsertionMode = InsertionMode.Replace,
.UpdateTargetId = "modPop",
.OnBegin = "readyTheButton()"})</text>)
Pretty simple, the $(document).ready(function () { }); event is only fired when the page is loaded and everything is ready. But when you page the grid, all the buttons are reloaded by ajax and non of them has the click event attached.
1fst Solution:
Look in the documentation for the paging event of your grid (usually every grid has such an event), attach the click event to your actionlinks everytime the grid has changed the page.
2nd Solution:
Apply an onclick attribute to your actionlinks on the server, this onclick can lead to your InitializeDialog function.
(Edit) Addition: You could try not to use a javascript event handler, but the built in Ajax Actionlink. This will keep your page clean and you don't have to deal with javascript event handling.
I am using a jQuery datatable with bottom pagination. When the pages are clicked from bottom , I want it to scroll it to top, so users do not have to manually do that for longer pages. I tried using dataTables_scrollBody, but it doesn't work properly
Here is my code:
oTable = $('#tTable').dataTable({
"fnDrawCallback": function(o) {
$('dataTables_scrollBody').scrollTop(0);
}
});
The page scrolls to top only when you click first/last (which I think is default behaviour), but not with every page click.
Update. The original answer was targeting 1.9.x. In dataTables 1.10.x it is much easier :
table.on('page.dt', function() {
$('html, body').animate({
scrollTop: $(".dataTables_wrapper").offset().top
}, 'slow');
});
demo -> http://jsfiddle.net/wq853akd/
Also, if you're using the bootstrap version of datatables, you may notice that when using the fix, the page actually scrolls back down after scrolling to the top. This is because it is focusing on the clicked button as per this datatables.net thread. You can fix this by simply focusing on the table header after the animate call, like so:
table.on('page.dt', function() {
$('html, body').animate({
scrollTop: $(".dataTables_wrapper").offset().top
}, 'slow');
$('thead tr th:first-child').focus().blur();
});
Original Answer
You should target .dataTables_wrapper and attach the event to .paginate_button instead. Here with a nice little animation :
function paginateScroll() {
$('html, body').animate({
scrollTop: $(".dataTables_wrapper").offset().top
}, 100);
console.log('pagination button clicked'); //remove after test
$(".paginate_button").unbind('click', paginateScroll);
$(".paginate_button").bind('click', paginateScroll);
}
paginateScroll();
see fiddle -> http://jsfiddle.net/EjbEJ/
Since Datatables 1.10 there is this page event
https://datatables.net/reference/event/page
So one can use
$('#example_table').on( 'page.dt', function () {
$('html, body').animate({
scrollTop: 0
}, 300);
} );
Demo: https://jsfiddle.net/mcyhqrdx/
This worked out for me.
$(document).ready(function() {
var oldStart = 0;
$('#example').dataTable({
"bJQueryUI": true,
"sPaginationType": "full_numbers",
"fnDrawCallback": function (o) {
if ( o._iDisplayStart != oldStart ) {
var targetOffset = $('#example').offset().top;
$('html,body').animate({scrollTop: targetOffset}, 500);
oldStart = o._iDisplayStart;
}
}
});
} );
I'm also using datatables and Allan's solution (found here) worked perfectly for me.
$(document).ready(function() {
var oldStart = 0;
$('#example').dataTable({
"bJQueryUI": true,
"sPaginationType": "full_numbers",
"fnDrawCallback": function (o) {
if ( o._iDisplayStart != oldStart ) {
var targetOffset = $('#example').offset().top;
$('html,body').animate({scrollTop: targetOffset}, 500);
oldStart = o._iDisplayStart;
}
}
});
} );
Thank's from davidkonrad. But when I used his code, after I clicked on paginate button, scroll of page went to top and then after load data, scroll backed to bottom.
I combined multiple posts in StackOverFlow and Datatables forum.
I defined a global variable :
var isScroll = false
When it's clicked on paginate button isScroll set to true:
$(document).on('click', '.paginate_button:not(.disabled)', function () {
isScroll = true;
});
And finally:
$(document).ready(function () {
$('#myDataTable').DataTable({
...
"fnDrawCallback": function () {
if (isScroll) {
$('html, body').animate({
scrollTop: $(".dataTables_wrapper").offset().top
}, 500);
isScroll = false;
}
},
...
});
});
Thanks from #0110
None of the above answers worked for me. Here's my solution.
$("#divContainingTheDataTable").click(function(event){
if ($(event.target).hasClass("paginate_button")) {
$('html, body').animate({
scrollTop: $("#divContainingTheDataTable").offset().top
}, 200);
}
});
I tried targetting .paginate_button but it never seemed to fire. My approach checks the div containing the datatable, if you click on the pagination buttons, the page scrolls up to the top of the container.
For those using the bootstrap version of Datatables:
You may notice that when using the fix from the accepted answer above, the page actually scrolls back down to the paging controls after scrolling to the top. This is because it is focusing on the clicked paging button as per this datatables.net thread. You can fix this by simply focusing on the table header after the animate call like so:
table.on('page.dt', function() {
$('html, body').animate({
scrollTop: $(".dataTables_wrapper").offset().top
}, 'slow');
$('thead tr th:first-child').focus().blur();
});
Note: the chained blur()'ing is done so that you the user doesn't see any focused styles on th:first-child.
I have a dojox.layout.FloatingPane (as a custom dijit) which can be positioned anywhere within its enclosing div. My problem is that the user can potentially drag the FloatingPane completely outside of its container and be unable to retrieve it. Is there any easy way to force the FloatingPane to remain entirely visible at all times?
Here's my code:
dojo.provide("ne.trim.dijits.SearchDialog");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.require("dojox.layout.FloatingPane");
dojo.declare("ne.trim.dijits.SearchDialog", [dijit._Widget, dijit._Templated], {
templateString: dojo.cache("ne.trim.dijits", "templates/SearchDialog.html"),
initialised:false,
floatingPane: null,
postCreate: function() {
this.init();
},
init: function() {
console.debug("SearchDialog.init()", "start");
if ( this.initialised === false ) {
this.createSearchDialog();
}
//ne.trim.AppGlobals.searchDialog = this;
console.debug("SearchDialog.init()", "end");
},
createSearchDialog: function() {
var node = dojo.byId('searchbox');
floatingPane = new dojox.layout.FloatingPane({
title: "A floating pane",
resizable: true, dockable: true, constrainToContainer: true,
style: "position:absolute;top:100;right:100;width:400px;height:300px;z-index:100",
}, node );
this.initialised=true;
floatingPane.startup();
}
});
First of all, see the working example at jsFiddle: http://jsfiddle.net/phusick/3vTXW/
And now some explanation;) The DnD functionality of FloatingPane is achieved via dojo.dnd.Moveable class instantialized in pane's postCreate method. To constrain the movement of the FloatingPane you should use one of these moveables instead:
dojo.dnd.parentConstainedMoveable - to constrain by a DOM node
dojo.dnd.boxConstrainedMoveable - to constrain by co-ordinates: {l: 10, t: 10, w: 100, h: 100}
dojo.dnd.constrainedMoveable - to constrain by co-ordinates calculated in a provided function
For more details see aforementioned jsFiddle.
According to documentation you should call destroy() on Moveable instance to remove it, but as FloatingPane's original Moveable is not assigned to any object property, I do not destroy it, I just instantiate one of those three moveables on the same DOM node in a subclass:
var ConstrainedFloatingPane = dojo.declare(dojox.layout.FloatingPane, {
postCreate: function() {
this.inherited(arguments);
this.moveable = new dojo.dnd.move.constrainedMoveable(this.domNode, {
handle: this.focusNode,
constraints: function() {
return dojo.coords(dojo.body());
}
});
}
});
Now you can use ConstainedFloatingPane instead of dojox.layout.FloatingPane:
var floatingPane = new ConstrainedFloatingPane({
title: "A Constrained Floating Pane",
resizable: true
}, searchboxNode);