Unselecting cell with cellNav in ui-grid - angular-ui-grid

This is my first time using ui-grid and I'm finding the API a bit frustratingly limited.
I'm using edit and cellnav together. I have edit on focus turned on, so a single click switches the cell to edit mode. When I click e.g. outside the grid, the edit closes on blur but the cell remains selected. The problem with this is that in a selected cell, clicking once does not put the cell in edit mode.
So, I'm looking for either:
a) A way to deselect the cell when edit closes, or:
b) A way for single-click in a selected cell to switch it to edit mode.
Searching the API and Tutorial docs has not yielded a way to do either.
Thanks
Edit: Since I could find no other way to do it I wrote this horrible directive, which I urge you not to copy and use in your own projects. I'm hoping someone will reply with a less loathsome and brittle suggestion, but for now this is all I have.
(function () {
angular.module('eventApp').directive('autoEdit', function () {
return function (scope, element, attrs) {
function doubleClick() {
$(this, '.ui-grid-cell-focus').dblclick();
}
$(element).on('blur', '.ui-grid-cell-focus ~ div input', function () {
$(this).closest('div').parent().children('.ui-grid-cell-focus').unbind('click', doubleClick).click(doubleClick);
});
}
});
})();

I think you can try to use this "undocumented" functionality:
gridApi.grid.cellNav.clearFocus();
gridApi.grid.cellNav.lastRowCol = null;

This is my solution using a decorator to expose a working clearFocus method onto the cellNav API.
angular.module(...)
.config(
$provide => {
$provide.decorator('uiGridCellnavDirective', $delegate => {
const {compile} = $delegate[0];
$delegate[0].compile = () => {
const compilation = compile(), {pre} = compilation;
compilation.pre = ($scope, $elm, $attrs, uiGridCtrl) => {
const result = pre($scope, $elm, $attrs, uiGridCtrl);
uiGridCtrl.grid.api.cellNav.clearFocus = () => {
uiGridCtrl.grid.cellNav.lastRowCol = null;
uiGridCtrl.cellNav.clearFocus();
};
return result;
};
return compilation;
}
return $delegate;
});
}
)

Extending #Vlad answer
gridApi.grid.cellNav.clearFocus();
gridApi.grid.cellNav.lastRowCol = null;
gridApi.grid.columns[0].colDef.allowCellFocus = false;
[to fix the issue of clearing selection of first column due to the fix]

Related

Turbolinks unfriendly?

I totally get why Turbolinks 5 is awesome and if you're reading it, you probably do as well, but I am very frustrated with how badly it plays with the other scripts on the block.
To date, there is no simple explanation (human readable) that shows how to wrap existing jQuery scripts in a way that would allow them to function.
Take for example this one: https://github.com/Bttstrp/bootstrap-switch. It's well written, simple to understand. You load the js and css to your assets pipeline and instantiate it on some page.
# view.html.erb
<input type="checkbox" class="switch"> switch button
<script type="text/javascript">
$(".switch").bootstrapSwitch();
</script>
you go to view.html, click another page, click back and you see two buttons.
Next, you spend 5 hours looking for a way to have Turbolinks load the instance of bootstrapSwitch only once if not loaded before. Well, even if you do, the functionality will be gone. Clicking it will not work.
$(document).on("turbolinks:load", function()... will load it on every Turbolink visit, and for now, the only way I could make it work and not create duplicates was to disable cache on view.html with
<%= content_for :head do %>
<meta name="turbolinks-cache-control" content="no-cache">
<% end %>
Which feels kinda stupid.
I think it all has something to do with using idempotent - https://github.com/turbolinks/turbolinks#making-transformations-idempotent but how do you practically do this?
Could someone please take this simple plugin as an example and share a simple, elegant solution for making it work which we can then reproduce with other scripts?
Developing apps with Turbolinks does require a particular approach in order to get things running smoothly. Due to differences the way pages are loaded and cached, some patterns of running scripts won't behave in the same way with Turbolinks vs. without. This may seem unfriendly at first, and the "gotchas" can be frustrating, but I've found that with a little understanding, it encourages more organised, robust code :)
As you have figured out, the problem with duplicate switches is that the plugin is being called more than once on the same element. This is because Turbolinks caches a page just before navigating away from it, and so the cached version includes any dynamically added HTML[1] e.g. stuff added via plugins. When navigating back/forward, the cached version is restored, and the behaviour is duplicated :/
So how to fix this? When working with code which adds HTML or event listeners, it is generally a good idea to teardown behaviours before the page is cached. The Turbolinks event for that is turbolinks:before-cache. So your setup/teardown might be:
// app/assets/javascripts/switches.js
$(document)
.on('turbolinks:load', function () {
$('.switch').bootstrapSwitch()
})
.on('turbolinks:before-cache', function () {
$('.switch').bootstrapSwitch('destroy')
})
This is a bit difficult to test since all the setup and teardown is done in event handlers. What's more, there maybe many more cases like this, so to prevent repitition, you may want to introduce your own "mini-framework" for setting up and tearing down functionality. The following walks through creating a basic framework.
Here's is what we'll aim for: calling window.App.addFunction with a name and a function registers a function to call. That function gets the elements and calls the plugin. It returns an object with a destroy function for teardown:
// app/assets/javascripts/switches.js
window.App.addFunction('switches', function () {
var $switches = $('.switch').bootstrapSwitch()
return {
destroy: function () {
$switches.bootstrapSwitch('destroy')
}
}
})
The following implements addFunction, storing added functions in the functions property:
// app/assets/javascripts/application.js
// …
window.App = {
functions: {},
addFunction: function (name, fn) {
this.functions[name] = fn
}
}
We'll call each function when the app initializes, and store the result of each function call in the results array if it exists:
// app/assets/javascripts/application.js
// …
var results = []
window.App = {
// …
init: function () {
for (var name in this.functions) {
var result = this.functions[name]()
if (result) results.push(result)
}
}
}
Tearing down the app involves destroying calling destroy (if it exists) on any results:
// app/assets/javascripts/application.js
// …
window.App = {
// …
destroy: function () {
for (var i = 0; i < results.length; i++) {
var result = results[i]
if (typeof result.destroy === 'function') result.destroy()
}
results = []
}
}
Finally we initialise and teardown the app:
$(document)
.on('turbolinks:load', function () {
window.App.init.call(window.App)
})
.on('turbolinks:before-cache', window.App.destroy)
So to put this all together:
;(function () {
var results = []
window.App = {
functions: {},
addFunction: function (name, fn) {
this.functions[name] = fn
},
init: function () {
for (var name in this.functions) {
var result = this.functions[name]()
if (result) results.push(result)
}
},
destroy: function () {
for (var i = 0; i < results.length; i++) {
var result = results[i]
if (typeof result.destroy === 'function') result.destroy()
}
results = []
}
}
$(document)
.on('turbolinks:load', function () {
window.App.init.call(window.App)
})
.on('turbolinks:before-cache', window.App.destroy)
})()
Functions are now independent of the event handler that calls them. This decoupling has a couple of benefits. First it's more testable: functions are available in window.App.functions. You can also choose when to call your functions. For example, say you decide not to use Turbolinks, the only part you'd need to change would be when window.App.init is called.
[1] I think this is better than the default browser behaviour (where pressing "Back" returns the user back to the page as it was when it was first loaded). A Turbolinks "Back" returns the user back to the page as they left it, which is probably what a user expects.

DevExpress CallbackPanel PerformCallback hangs when content includes PageControl or TabControl

I would like to refresh the tabs in my TabControl on demand, when a separate client action occurs on the page. I have placed my TabControl extension (tried PageControl also) within a CallbackPanel, and the EndCallBack event never fires. If ShowLoadingPanel is set to true, you see that the call is hanging because the loading panel never disappears. Both OnBeginCallback and the actual Controller callback action are executed. I assume there are some sort of conflicting callbacks occuring between the panel and tabs but I cannot figure out how to resolve it. If I replace the TabControl with basic html or other simpler DevExpress controls, everything works fine.
TabControl Partial (CallbackTestPageControl.cshtml):
#Html.DevExpress().TabControl(settings => {
settings.Name = "testTabControl";
settings.Width = Unit.Percentage(100);
settings.Tabs.Add("tab 1");
settings.Tabs.Add("tab 2");
settings.Tabs.Add("tab 3");
}).GetHtml()
Panel Partial (CallbackTestPanel.cshtml):
#Html.DevExpress().CallbackPanel(settings =>
{
settings.Name = "cbpTabStrip";
settings.CallbackRouteValues = new { Controller = "Home", Action = "CallbackTestPanel" };
settings.ClientSideEvents.BeginCallback = "OnBeginCallback";
settings.ClientSideEvents.EndCallback = "OnEndCallback";
settings.SetContent(() => Html.RenderPartial("CallbackTestPageControl"));
}).GetHtml()
View (CallbackTest.cshtml):
<script type="text/javascript">
var testId = null;
function ButtonClicked(s, e) {
alert('click');
testId = 1;
if (!cbpTabStrip.InCallback())
cbpTabStrip.PerformCallback();
}
function OnBeginCallback(s, e) {
alert('begin');
e.customArgs["Id"] = testId;
testId = null;
}
function OnEndCallback(s, e) {
alert('end');
if (testId != null)
cbpTabStrip.PerformCallback();
}
</script>
#Html.DevExpress().Button(settings => {
settings.Name = "CallbackButton";
settings.Text = "Callback";
settings.ClientSideEvents.Click = "ButtonClicked";
}).GetHtml()
#Html.Partial("CallbackTestPanel")
Controller (HomeController.cs):
public ActionResult CallbackTest()
{
return View();
}
public ActionResult CallbackTestPanel()
{
int id = !String.IsNullOrEmpty(Request.Params["Id"]) ? int.Parse(Request.Params["Id"]) : 0;
return PartialView("CallbackTestPanel");
}
ADDITIONAL INFO: Also, I have tried updating the DevExpress configuration in the web.config based on other suggestions online. Specifically - updating the enableResourceMerging attribute on the compression element to false rather than true. This seemed to allow the callback to end intermittantly. I really don't want to disable resource merging anyway, so I'm actually glad this didn't provide a reliable solution. So, this is what I currently have:
<devExpress>
<themes enableThemesAssembly="true" styleSheetTheme="" theme="Office2010Silver" />
<compression enableHtmlCompression="true"
enableCallbackCompression="true"
enableResourceCompression="true"
enableResourceMerging="true" />
<settings rightToLeft="false" />
<errors callbackErrorRedirectUrl="" />
</devExpress>
I'm sorry if I wasted anyone's time on this. In the end, the problem was that I had all my non-DevExpress scripts at the bottom of my layout body. I needed to move jQuery into the head prior to the DevExpress scripts. Strangely enough, everything else had been working fine prior to this issue. Thanks to anyone who tried to reproduce.
I know this is old but my issue is I had caching enabled that form i.e.
Once I removed that everything worked. Hope this helps someone else in the future.

Knockout, CKEditor & Single Page App

I have a situation involving KnockoutJS & CKEditor.
Basically we've got part of our site that is 'single page' app style, currently it just involves 2 pages but will likely expand over time, currently it's just a 'listings' page and a 'manage' page for the items in the list.
The manage page itself requires some sort of rich text editor, we've gone with CKEditor for a company wide solution.
Because these 2 pages are 'single page' style obviously CKEditor can't register against the manage elements because they aren't there on page load - simple enough problem to fix. So as a sample I attached CKEditor on a click event which worked great. The next problem was that then the Knockout observables that had been setup weren't getting updated because CKEditor doesn't actually modify the textarea it's attached too it creates all these div's/html elements that you actually edit.
After a bit of googleing I found an example of someone doing this with TinyMCE - http://jsfiddle.net/rniemeyer/GwkRQ/ so I thought I could adapt something similar to this for CKEditor.
Currently I'm quite close to having a working solution, I've got it initialising and updating the correct observables using this technique (I'll post code at the bottom) and even posting back to the server correctly - fantastic.
The problem I'm currently experiencing is with the 'Single Page' app part and the reinitialisation of CKEditor.
Basically what happens is you can click from list to manage then save (which goes back to the list page) then when you go to another 'manage' the CKEditor is initialised but it doesn't have any values in it, I've checked the update code (below) and 'value' definitely has the correct value but it's not getting pushed through to the CKEditor itself.
Perhaps it's a lack of understanding about the flow/initialisation process for CKEditor or a lack of understanding about knockout bindings or perhaps it's a problem with the framework that's been setup for our single page app - I'm not sure.
Here is the code:
//Test one for ckeditor
ko.bindingHandlers.ckeditor = {
init: function (element, valueAccessor, allBindingsAccessor, context) {
var options = allBindingsAccessor().ckeditorOptions || {};
var modelValue = valueAccessor();
$(element).ckeditor();
var editor = $(element).ckeditorGet();
//handle edits made in the editor
editor.on('blur', function (e) {
var self = this;
if (ko.isWriteableObservable(self)) {
self($(e.listenerData).val());
}
}, modelValue, element);
//handle destroying an editor (based on what jQuery plugin does)
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
var existingEditor = CKEDITOR.instances[element.name];
existingEditor.destroy(true);
});
},
update: function (element, valueAccessor, allBindingsAccessor, context) {
//handle programmatic updates to the observable
var value = ko.utils.unwrapObservable(valueAccessor());
$(element).html(value);
}
};
So in the HTML it's a fairly standard knockout 'data-bind: ckeditor' that applyies the bindings for it when the ViewModel is initialised.
I've put debugger; in the code to see the flow, it looks like when I load the first time it calls init, then update, when I go in the second time it hits the ko.utils.domNodeDisposal to dispose of the elements.
I've tried not destroying it which CKEditor then complains that something already exists with that name. I've tried not destroying it and checking for if it exists and initialising if it doesn't - that works the first time but the second time we have no CKEditor.
I figure there's just one thing I'm missing that will make it work but I've exhausted all options.
Does anyone have any knowledge on integrating these 3 things that can help me out?
Are there any knockout experts out there that might be able to help me out?
Any help would be much appreciated.
MD
For anyone interested I sorted it:
All it was was a basic order of execution, I just needed to set the value to the textarea html before it got initialised.
Note this uses a jquery adaptor extension to do the .ckeditor() on the element.
There is probably also a better way to do the 'blur' part.
This extension also doesn't work with options at the moment but that should be quite simple in comparison.
ko.bindingHandlers.ckeditor = {
init: function (element, valueAccessor, allBindingsAccessor, context) {
var options = allBindingsAccessor().ckeditorOptions || {};
var modelValue = valueAccessor();
var value = ko.utils.unwrapObservable(valueAccessor());
$(element).html(value);
$(element).ckeditor();
var editor = $(element).ckeditorGet();
//handle edits made in the editor
editor.on('blur', function (e) {
var self = this;
if (ko.isWriteableObservable(self)) {
self($(e.listenerData).val());
}
}, modelValue, element);
}
};
I've been working with this for a while now and ran again several problems with the .on("blur") approach. Namely, when people clicked in to the rich text and entered text then scrolled directly to the Save button on my form, the observable didn't get updated fast enough. There are a ton of ways to handle delays, but I wanted something more official. I dug in to the CKEditor documentation and found this gem: focusManager
This is built-in functionality that handles all the instances of focus and blur and allows you to hook up a true blur event to the control.
Here is my bindingHandler for rich text then
ko.bindingHandlers.richText = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var txtBoxID = $(element).attr("id");
var instance = CKEDITOR.instances[txtBoxID];
var options = allBindingsAccessor().richTextOptions || {};
options.toolbar_Full = [
['Source', '-', 'Format', 'Font', 'FontSize', 'TextColor', 'BGColor', '-', 'Bold', 'Italic', 'Underline', 'SpellChecker'],
['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote', 'CreateDiv', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock', '-', 'BidiLtr', 'BidiRtl'],
['Link', 'Unlink', 'Image', 'Table']
];
//handle disposal (if KO removes by the template binding)
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
if (CKEDITOR.instances[txtBoxID]) { CKEDITOR.remove(CKEDITOR.instances[txtBoxID]); };
});
$(element).ckeditor(options);
//wire up the blur event to ensure our observable is properly updated
CKEDITOR.instances[txtBoxID].focusManager.blur = function () {
var observable = valueAccessor();
observable($(element).val());
};
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var val = ko.utils.unwrapObservable(valueAccessor());
$(element).val(val);
}
}
Building up on the work done in the other answers here's my solution:
handles changes using ckeditor's own change event (updates on keypress but not just that)
uses ckeditor's getData() so you don't get unwanted HTML like "magic line" and similar stuff
handles memory management (untested)
Code:
ko.bindingHandlers.ckeditor = {
init: function(element, valueAccessor, allBindingsAccessor, context) {
var options = allBindingsAccessor().ckeditorOptions || {};
var modelValue = valueAccessor();
var value = ko.utils.unwrapObservable(valueAccessor());
$(element).html(value);
$(element).ckeditor();
var editor = $(element).ckeditorGet();
//handle edits made in the editor
editor.on('change', function(e) {
var self = this;
if (ko.isWriteableObservable(self)) {
self($(e.listenerData).val());
}
}, modelValue, element);
//handle disposal (if KO removes by the template binding)
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
if (editor) {
CKEDITOR.remove(editor);
};
});
},
update: function(element, valueAccessor, allBindingsAccessor, context) {
// handle programmatic updates to the observable
var newValue = ko.utils.unwrapObservable(valueAccessor());
if ($(element).ckeditorGet().getData() != newValue)
$(element).ckeditorGet().setData(newValue)
}
};
The markup I use (note the afterkeydown):
<textarea
id="editor1"
data-bind="ckeditor: text, valueUpdate: 'afterkeydown'"
></textarea>
Update: as requested in the comments, here is a minimal working Fiddle.
First post so let me know if I've done anything wrong
In my project, I gave visual feedback as to whether there were unsaved changes and so needed the observable updated on keyup. And on click for when a toolbar button was clicked. This also was consistent with me using valueUpdate:['afterkeydown','propertychange','input'] in my data-bind attributes.
Also, for performance, I used the callback method parameter of .ckeditor(callback,options) rather than .on(eventName,handler).
This is the custom binding I came up with:
ko.bindingHandlers.ckeditor = {
init: function (element, valueAccessor, allBindingsAccessor, context) {
// get observable
var modelValue = valueAccessor();;
$(element).ckeditor(function(textarea) {
// <span> element that contains the CKEditor markup
var $ckeContainer = $(this.container.$);
// <body> element within the iframe (<html> is contentEditable)
var $editorBody =
$ckeContainer.find('iframe').contents().find('body');
// sets the initial value
$editorBody.html( modelValue() );
// handle edits made in the editor - by typing
$editorBody.keyup(function() {
modelValue( $(this).html() );
});
// handle edits made in the editor - by clicking in the toolbar
$ckeContainer.find('table.cke_editor').click(function() {
modelValue( $editorBody.html() );
});
});
// when ko disposes of <textarea>, destory the ckeditor instance
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).ckeditorGet().destroy(true);
});
},
update: function (element, valueAccessor, allBindingsAccessor, context) {
// handle programmatic updates to the observable
var newValue = ko.utils.unwrapObservable(valueAccessor());
var $ckeContainer = $(element).ckeditorGet().container;
if( $ckeContainer ) {
// <span> element that contains the CKEditor markup
$ckeContainer = $($ckeContainer.$);
// <body> element within the iframe (<html> is contentEditable)
var $editorBody =
$ckeContainer.find('iframe').contents().find('body');
// if new value != existing value, replace it in the editor
if( $editorBody.html() != newValue )
$editorBody.html( newValue );
}
}
};
Justification:
I know I should probably use .getData() and .setData(html) instead of this rather hacky way of finding <body> and <table class="cke_editor"> within the iframe contents.
Reason being, for update: the condition within:
if( $(element).ckeditorGet().getData() != newValue )
$(element).ckeditorGet().setData( newValue )
was initially true due to HTML formatting that CKEditor does. And so, notified the user about a dirty record even though it wasn't. Very specific to me so I thought you should know, in case you were wondering why.
I just used this technique with CKEditor 4 to overwrite the existing (1-way) "html" binding with a 2-way binding. I'm using the inline CKEditor which may behave differently (not sure) than the full/static editor. I started with the "value" binding and tweaked it to work with the innerHTML instead:
ko.bindingHandlers.html = {
'init': function (element, valueAccessor, allBindingsAccessor) {
var eventsToCatch = ["blur"];
var requestedEventsToCatch = allBindingsAccessor()["valueUpdate"];
var valueUpdateHandler = null;
if (requestedEventsToCatch) {
if (typeof requestedEventsToCatch == "string")
requestedEventsToCatch = [requestedEventsToCatch];
ko.utils.arrayPushAll(eventsToCatch, requestedEventsToCatch);
eventsToCatch = ko.utils.arrayGetDistinctValues(eventsToCatch);
}
valueUpdateHandler = function () {
var modelValue = valueAccessor();
var oldValue = ko.utils.unwrapObservable(modelValue);
var elementValue = element.innerHTML;
var valueHasChanged = (oldValue !== elementValue);
if (valueHasChanged)
modelValue(elementValue);
}
ko.utils.arrayForEach(eventsToCatch, function (eventName) {
var handler = valueUpdateHandler;
if (eventName.indexOf("after") == 0) {
handler = function () {
setTimeout(valueUpdateHandler, 0)
};
eventName = eventName.substring("after".length);
}
ko.utils.registerEventHandler(element, eventName, handler);
});
},
'update': function (element, valueAccessor) {
var newValue = ko.utils.unwrapObservable(valueAccessor());
var elementValue = element.innerHTML;
var valueHasChanged = (newValue !== elementValue);
if (valueHasChanged)
element.innerHTML = newValue;
}
};
Caveat: This should probably be updated to use CKEditor's own change event.
I rewrote this to update the observable on each keyup, instead of on blur. This is a lot more updates to the observable, but as long as you are saving with a button, this seems to work great so far!
//handle edits made in the editor
CKEDITOR.instances.thread_message.on('contentDom', function() {
CKEDITOR.instances.thread_message.document.on('keyup', function(e) {
var self = this;
if (ko.isWriteableObservable(self)) {
var ckValue = CKEDITOR.instances.element_id.getData();
self(ckValue);
//console.log("value: " + ckValue);
}
}, modelValue, element);
});
For the 'blur' part, I tried the code below and it seems to work
editor.on('blur', function (e) {
var self = this;
if (ko.isWriteableObservable(self)) {
var ckValue = e.editor.getData();
self(ckValue);
}
}, modelValue, element);
I think the 'Update' part is still needed if you "update" the observable from somewhere else (not through editing as this is taken care of by the 'blur')

what is the right emberjs way to switch between various filtering options?

I've an individualStore (extends from Em.ArrayController), whose task is to keep an array of individual objects. There are several APIs that my application calls, and they return individual objects which are sent to the store. Think about it as the database of cached individual records in my application.
App.individualStore = App.ArrayController.create({
allIndividuals: function () {
return this.get('content').sort(function (a, b) {
return (b.votes_count - a.votes_count);
});
}.property('#each.votes_count').cacheable(),
aliveIndividuals: function () {
return this.get('content').filter(function (individual) {
return (!!individual.living);
}).sort(function (a, b) {
return (b.votes_count - a.votes_count);
});
}.property('#each.living', '#each.votes_count').cacheable(),
deceasedIndividuals: function () {
return this.get('content').filter(function (individual) {
return (!individual.living);
}).sort(function (a, b) {
return (b.votes_count - a.votes_count);
});
}.property('#each.living', '#each.votes_count').cacheable()
});
My view has a `individualsBinding: 'App.individualStore.allIndividuals', which renders up as intended perfectly.
I want to add filtering buttons, e.g. Show: All | Alive | Deceased. What would be the right way to change the filtering here? Keep in mind that whatever the criteria is, I'd like it to keep in sync with individualStore always.
Someone suggested to change bindings on runtime,
this.bind('users', Ember.Binding.from('App.individualStore.aliveIndividuals'));
This works in my first two-three clicks on these buttons, but then it freezes the browser (sort of infinite loop?).
This also doesn't feel like the best option to me. I'm new to ember, so anything you say would be helpful. Thanks in advance.
I would make the filter function itself a property and by changing a filterName on the controller, you are notified and accordingly update the filtered content, see http://jsfiddle.net/pangratz666/ypcLq/
App.controller = Ember.ArrayProxy.create({
content: [],
filterName: 'all',
allFilter: function() {
return true;
},
aliveFilter: function(individual) {
return ( !! individual.living);
},
deceasedFilter: function(individual) {
return (!individual.living);
},
filtered: function() {
var filterName = this.get('filterName');
var filterFunc = this.get(filterName + 'Filter');
return this.filter(filterFunc).sort(function(a, b) {
return (b.votes_count - a.votes_count);
});
}.property('content.#each', 'filterName').cacheable()
});
So you can later in your view set the filter which shall be used via App.controller.set('filterName', 'alive').
Just as a note: you can chain filters via this.filter(filterFunc1).filter(filterFunc2) so you could for example filter all alive individuals of a specific age, ...

Dotnetnuke partial rendering make my jQueryUI widget stop working

I want to use tab widget of jQueryUI in dotnetnuke 5.6.3
I registered jQueryUI in my module and it works fine but when I use partial Rendering in my page it fails to load.
Here is my code:
$(document).ready(function () {
rastaAdmin();
});
function rastaAdmin() {
var tabdiv = $('#tabul');
var tabvar = tabdiv.tabs();
}
this site have a method to solve my problem but it doesn't work in my script.
After reading the above site I changed my code to:
$(document).ready(function () {
rastaAdmin();
});
function pageLoad(sender, args) {
rastaAdmin();
}
function rastaAdmin() {
var tabdiv = $('#tabul');
var tabvar = tabdiv.tabs();
}
This Doesn't work for me.
What Can I do?
Thank You
I've had issues using the pageLoad function as well (though I don't remember now where it ended up breaking down). However, something like the other method should work fine (see the new jQuery UI setup in the core modules in DNN 6):
$(document).ready(function () {
setupDnnSiteSettings();
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function () {
setupDnnSiteSettings();
});
});
The one caveat here is that this registers the setup code to happen after returning from any UpdatePanel-initiated request, not just your specific UpdatePanel. Calling tabs again on the same element shouldn't cause any issue, but you'll want to figure out a way to differentiate if you're doing something that should only be called once.
Thank you bdukes
After your help, I changed my code to:
$(document).ready(function () {
Sys.Application.add_load(function (s, e) { rastaAdmin(); });
rastaAdmin();
});
function rastaAdmin() {
var tabdiv = $('#tabul');
var tabvar = tabdiv.tabs();
}
And It Works Like a charm for me! Thank You mate.

Resources