Disable entire jqGrid - jquery-ui

I have been looking for methods on how to disable a jqGrid and I found some:
Using BlockUI plugin: http://jquery.malsup.com/block/
Using jqGrid options: loadui and set it to 'block'
First option is a great solution (I have not tried yet) and it is clearer maybe but I want to avoid using plugins if I can whenever I can do it by setting object properties so I am trying the second option but it is not working for me, jqGrid continues enabled.
My jqgrid in my asp.net mvc 4 view:
<div id="jqGrid">
#Html.Partial("../Grids/_PartialGrid")
</div>
and _PartialGrid:
<table id="_compGrid" cellpadding="0" cellspacing="0">
</table>
<div id="_compPager" style="text-align: center;">
</div>
so in the view, in script section I perform below on document ready and depending on the status of a property in my model (I disable it if id>0, otherwise I enable it on page reload):
#section scripts
{
#Content.Script("/Grids/CompGrid.js", Url) // Content is a helper javascript loader (see end of this post)
}
<script type="text/javascript">
$(document).ready(function () {
showGrid();
var disableCompGrid = #Html.Raw(Json.Encode(Model.ItemCompViewModel));
setStatusCompGrid(disableCompGrid.id > 0);
}
</script>
CompGrid.js is:
function showGrid() {
$('#_compGrid').jqGrid({
caption: paramFromView.Caption,
colNames: ....
}
function setStatusCompGrid(disabled) {
$('#_compGrid').jqGrid({
loadui: 'block',
loadtext: 'Processing...'
});
}
In the code above, also I have tried to pass as parameter disabled to showGrid function and depending on if it is true or false to set a variable to 'block' or 'enable' respectively and then setting loadui property with this variable but it is not working.
Content.cshtml:
#using System.Web.Mvc;
#helper Script(string scriptName, UrlHelper url)
{
<script src="#url.Content(string.Format("~/Scripts/{0}", scriptName))" type="text/javascript"></script>
}
Any ideas?

It's important to understand that the call $('#_compGrid').jqGrid({...}); converts initial empty <table id="_compGrid"></table> element to relatively complex structure of dives and tables. So you can do such call only once. Such call creates and initialize the grid. In other words the function showGrid has bad name. The function can be called only once. The second call of it will test that the grid already exist and it will do nothing. If you need to change some parameters of existing grid you can use setGridParam method.
In the case you can use absolutely another solution to block the grid. After the call $('#_compGrid').jqGrid({...}); the DOM element of the initial table get some expandos - new property or method. For example $('#_compGrid')[0] will contains grid property which contains beginReq and endReq methods. So you can first create the grid (in the showGrid function) and include options loadui: 'block' and loadtext: 'Processing...' in the list of options which you use. Then if you need to block the grid later you can use
$('#_compGrid')[0].grid.beginReq();
and the code
$('#_compGrid')[0].grid.endReq();
to remove blocking. See the demo which demonstrates this. Alternatively you can show overlays created by jqGrid manually like I described in the answer. The code will be simple enough:
var gridId = "_compGrid"; // id of the grid
...
$("#lui_" + gridId).show();
$("#load_" + gridId).text("Processing...").show();
to show the overlay and
$("#lui_" + gridId).hide();
$("#load_" + gridId).hide();
to hide the overlay. See another demo which works exactly like the first one.

you don't need any plugin. Just add/remove css:
.disabled {
pointer-events: none;
//optional
opacity: 0.4;
}
DEMO

Related

passing backbone collection to view

I'm just starting out with backbone / grails and i've been struggling to figure out how to get everything to work.
I'm building a pricing configurator where a user selects a product type from radio group A and radio group B containing the quantity / pricing / discount data will do an ajax call to the backend for updated pricing data. I do not want to expose my pricing algorithm to the front end, so I was thinking I would use backbone to handle my ajax request / template.
I do not want to fully rely on js to create my UI, so on the initial page load, I'll build the gsp view with grails. Only problem I've noticed was my gsp view was being replaced by my handlebars template on initial page load. I guess this is fine, except it does two identical queries which isn't optimal.
Anyhow my code that does not seem to be working.
<script id="priceTemplate" type="text/x-handlebars-template">
<tr>
<td><input type="radio" value="" name="quantity">{{quantity}}</td>
<td class="price"><span>{{price}}</span></td>
<td class="discount"><span>{{discount}}</span></td>
</tr>
</script>
<asset:javascript src="bb_product/config.js"/>
<script>
var prices = new models.PriceList([],{productId:${productInstance.id}});
var priceView = new PriceView({collection: prices});
prices.fetch();
</script>
Models
var models = {};
models.PriceModel = Backbone.Model.extend({
//Is the model automatically populated from the collections json response?
})
models.PriceList = Backbone.Collection.extend({
initialize: function(models, options) {
this.productId = options.productId;
},
model: models.PriceModel,
url: function() {
return '../product/pricing/' + this.productId + '.json'
}
});
View
var PriceView = Backbone.View.extend({
el: '#product-quantities',
template: Handlebars.compile($("#priceTemplate").html()),
initialize: function(){
this.render();
},
render: function() {
console.log('collection ' + this.collection.toJSON()) //comes back empty
this.$el.html( this.template(this.collection.toJSON()));
}
});
json returned from url
[{"id":1,"quantity":10,"price":"10","discount":"10"},{"id":2,"quantity":50,"price":"20","discount"
:"10"}]
To initially get this up and working, what am I missing to display all items in the json object?
I've also see this code around, not sure what it does this.listenTo(this.collection, 'reset', this.render);
The reason you don't see any items is that the items aren't actually in the collection until after the view is rendered. Look at these two lines of code:
var priceView = new PriceView({collection: prices});
prices.fetch();
The first line renders the view (since you're calling render from within initialize). However, at that time, the prices collection is empty. Then, the second line fetches the data from the server and loads it into the collection; but by that time, the view has been rendered.
That last line of code you posted is the key to fixing this:
this.listenTo(this.collection, 'reset', this.render);
Usually, you'll put this inside the initialize function in your view class. What this does is "listen" to the collection instance, and when the reset event occurs, it will call the this.render function. (Of course, the method this.listenTo can "listen" to other objects for other events; see more details in the Backbone documentation).
If you add that line to the view's initialize function, the view will re-render whenever a "reset" event happens on the collection.
HOWEVER, by default, the "reset" event happens when all the models in the collection are replaced with another set of models, and this doesn't happen by default when you call a collection's fetch method (instead, the collection will try to "smart-update"). To force a reset of the collection when using fetch, pass {reset: true} as a parameter:
prices.fetch({reset: true});

Ember: How to bind action to code generated with JS

I have a simple view which renders set of images depending on given items array (simplified code), using this as I need to collect some other data to 'build' required class name(s):
App.MyView = Ember.View.extend({
buildTemplate: function () {
var itemz = this.get('items');
var classname = 'classNameDependingOnSomeCalculations...';
var out = '<div>';
$.each(itemz, function (index, obj) {
out += '<img {{action myActionHere}} src="' + obj.href + '" alt="" class="'+classname+'"/>';
});
out += '</div>';
return out;
}.property('view'),
defaultTemplate: Ember.Handlebars.compile(
"<div>{{{view.buildTemplate}}}</div>"
)
});
And in template I'm using it as
{{#each myObj in myCollection}}
{{view App.MyView itemsBinding="myObj.items" otherBinding="otherProps" }}
{{/view}}
Unfortunately this way Ember instead of binding the action puts {{action myActionHere}} directly into code...
How can I bind an action instead while building dynamic template?
I'm using Ember 1.1.2
P.S. Or maybe I should use quite other approach for building this view?
There is a workaround to make this work with the view as you've laid it out here... But this is really not the ember way of doing it. If for some reason you need this kind of an approach, I'll append an answer for that, but I'm going to aim to fix the underlying issue.
Instead of doing this as shown here, you should instead have code that looks like the following directly in your JSP:
{{#each myObj in myCollection}}
<div>
{{#each item in myObj.items}}
<img {{action myActionHere}} src={{item.href}} alt='' class={{classNameFunction}}/>
{{/each}}
</div>
{{/each}}
If your reason for wanting to do this as a view is so that you can reuse this functionality without rewriting the code, take a look at partials which are specifically designed for that purpose.

Using data-direction with dynamically loaded pages

I'm trying to load dynamic pages with jQuery, following this example.
(EDIT): Updated the code to provide a better view of the context
Here is a code sample
<div data-role="page" id="pageSample">
<div data-role="header">title</div>
<div data-role="content">
<a href="#home" data-role="button" data-transition="slide" data-direction='reverse'>Home</a>
</div>
<div data-role="footer">Footer</div>
</div>
$(document).bind( "pagebeforechange", function( e, data ) {
// Generate dynamic content of targeted pages...
$.mobile.changePage($(page), {
transition:"slide",
dataUrl:url,
reverse:reverse
});
});
The back button may be dynamically generated or not (such as this snippet). In both cases, it does not work reverse, as changePage is triggered through pagebeforechange.
Therefore, I inserted a reverse variable in changePage() options.
I can't find a way to retrieve the data-direction value of the clicked item.
I tried this just before changePage():
reverse = false;
$('a[data-direction="reverse"]').on("click", function(){
reverse = true;
});
But the reverse value is not updated in changePage(). I guess both codes run synchronously.
Is there a way to update the reverse value in changePage() ?
Final update
As per our discussion and your example http://jsfiddle.net/Iris/UZBhx/21/
Change this
$('a').on("click", function()
to
$(document).on("click", 'a', function()
Another update
Binding the $.mobile.changePage to pagebeforechange triggers all your code twice. Thus you lose the value of reverse or it gets neglected when the command executes the first time.
Try binding it to pagebeforehide as below.
$(document).bind( 'pagebeforehide', '[data-role="page"]#PageId', function( e, data ) {
// Generate dynamic content of targeted pages...
$.mobile.changePage($(page), {
transition:"slide",
dataUrl:url,
reverse:reverse
});
});
Update
To use reverse effect on specific buttons, you can follow this method.
First, assign a class for buttons with reverse effect, e.g. ui-reverse and add the below script.
$(document).on('click', '[data-role='button'].ui-reverse', function() {
$.mobile.changePage( url, {
transition:"slide",
reverse: true,
dataUrl:url
});
});
"Back" button links - Jquery Mobile
data-direction="reverse"
Is meant to simply run the backwards version of the transition that will run on that page change, while data-rel="back" makes the link functionally equivalent to the browser's back button and all the standard back button logic applies.
data-rel="back"
This will mimic the back button, going back one history entry and ignoring the anchor's default href.
Adding data-direction="reverse" to a link with data-rel="back" will not reverse the reversed page transition and produce the "normal" version of the transition.
In your case, you want to reverse transition, use the below code.
$.mobile.changePage($(page), {
transition:"slide",
reverse: true, // this will reverse the affect of the transition used in the page.
dataUrl:url
});
Read more about it here.

jQuery UI tabs: How do I load a specific element from a different page?

I have jQuery UI tabs set up, but a problem that I'm having with links to different pages is that they load all contents of the page into the tab. This includes the footer, header, and other navbars that I don't want in the tab. What if I would only like to load a single ID from that page?
My tabs are set up this way:
<div id="mytabs">
<ul>
<li>Awesome page</li>
<li>Foo</li>
</ul>
</div>
Nothing much going on in the jQuery...
$(function() {
$( "#mytabs" ).tabs();
});
Let's say this is the html of "awesomepage" (that the first link targets):
<html>
<head>
<title>awesome page</title>
</head>
<body>
<div id="header">bla</div>
<div id="awesomeness">awesomeness!</div>
<div id="footer">fdsfd</div>
</body>
</html>
...And I only want the tab to load #awesomeness from the page. How would I go about doing this? I've read into some guides that do that by adding a data-target="#youridhere" attribute to the HTML, but I'm still confused on how to implement the javascript. It seems like this is a convenient solution, as I won't be targeting the same ID in every page. Any clues on how to get the javascript working?
Thanks in advance!
The function that allow to load partial code of the response is the $.load() function.
Unfortunately, the tabs() feature does not use this function but use $.ajax instead.
You can try this solution:
You can try to stop the default processing on the beforeLoad callback and manage your ajax call with the $.load() method.
(base on the 1.9 documentation, you may should adapt)
$('#tabs').tabs({
// Callback run when selecting a tab
beforeLoad: function(event, ui) {
// If the panel is already populated do nothing
if (ui.panel.children().size() > 0)
return false;
// Make your own ajax load (with fragment feature)
ui.panel.load(ui.tab.attr('href') + ' #yourFragment');
// stop the default process (default ajax call should not be launched)
return false;
});
NOTICE: I'm not sure about extracting the URL with ui.tab.attr('href'), check before what object is ui.tab, but it should be easy to retrieve the href parameter.
Good luck
Got the solution :) Using one of the answers as a reference point, the tabs can now load a single element specified in the data-target attribute. Here is the modified version:
$(function() {
$('#tabs').tabs(
{
beforeLoad: function(event, ui) {
if (ui.panel.children().size() > 0)
return false;
ui.panel.load($('a', ui.tab).attr('href') + $('a', ui.tab).attr('data-target'));
return false;
}
});
});

Controling height in jQuery UI Accordion with dynamic data

I'm using an jQuery accordion control with knockout to dynamically add/remove items to the control based on some client-side activity. I've created a knockout binding like such:
ko.bindingHandlers.accordion = {
init: function (element, valueAccessor) {
var options = valueAccessor() || {};
setTimeout(function () {
$(element).accordion(options);
}, 0);
//handle disposal (if KO removes by the template binding)
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).accordion("destroy");
});
},
update: function (element, valueAccessor) {
var options = valueAccessor() || {};
$(element).accordion("destroy").accordion(options);
}
}
Now my problem is the sizing of the accordion... it always looks very compressed (vertically). I've tried setting the height of the DIV that contains the control, like this:
<div id="LearningPaths" data-bind="foreach: allLearningPaths, accordion: {}" style="height:500px; border:1px solid red;">
But the panels in the accordion don't change... they still aren't very "tall". Here's what it looks like: http://sdrv.ms/STA9Y6
I think there's a setting I can pass in when I use the .accordion(), but with my binding handler I'm not sure how to do that as I'm already passing in the 'options' object.
What I want is to have the content area of each panel to expand to the entire available side in the accordion control... ideas?
First i think your problem is someone related to SharePoint web parts. I created a accordion solution which is based on the summary link web part in SharePoint and can be found here: http://www.n8d.at/blog/turn-summary-link-web-part-into-an-accordion/
I wrote my own accordion to accomplish this, which also makes sure that if you like to edit the page the accordion script won't be loaded.
On the other hand i think your problem is more related to css and not to jquery. Do you use float style in your css? Then you need to make sure that you use the so called clear-fix.
This can be done in define the following style:
.panel:after{
clear: both;
}

Resources