selection not working on WinJS ListView in click mode - javascript

Below is my WinJS.UI.ListView definition. However, onselectionchanged is never called when right clicking or doing Ctrl+Click. I have setup my ListView identically to the samples(which work). Am I missing something? Or could something be interfering, just with the click selection?
this.m_listView = new WinJS.UI.ListView(this.domNode,
{
layout : {type: WinJS.UI.GridLayout},
itemTemplate : this.itemTemplate.bind(this),
selectionMode: 'multi',
tapBehavior: 'invokeOnly',
swipeBehavior: 'select'
});
this.m_listView.oniteminvoked = this.itemInvoked.bind(this);
this.m_listView.onselectionchanged = this.selectionChanged.bind(this);
EDIT: I Assign my datasource in a separate function with these lines
var itemList = new WinJS.Binding.List(this.m_nodes);
this.m_listView.itemDataSource = itemList.dataSource;
This ListView is wrapped in a javascript class. So my template function is a prototype of my EntriesList class. This is that function(I pulled out the real content for simplicity, I still have this issue with the content though):
EntriesList.prototype.itemTemplate = function(itemPromise)
{
return itemPromise.then
(
function (item)
{
var entry = document.createElement("div");
entry.className = "tile";
entry.style.height = "120px";
entry.style.width = "340px";
return entry;
}
);

The issue was something in our internal API was blocking pointer events. We were able to resolve the problem. The code/configuration in the question works.

Related

CKEditor - Button to switch shown Toolbar

I'm trying to give a user the ability to swap around the toolbar between presets based on a button press. Ideally that button would be in the CKEditor screen, but I can play around with it.
I've found this SO Article in which I get the concept that you destroy your instance, and re-initialize it with a 'New Config'.
To follow suit I took one of the higher ranked responses, modified it to match my table, and threw it onto a button.
function toolbarSwap(){
var editor = CKEDITOR.instances.editor;
if (editor) { editor.destroy(true); }
CKEDITOR.config.toolbar_Basic = [['Bold','Italic','Underline',
'-','JustifyLeft','JustifyCenter','JustifyRight','-','Undo','Redo']];
CKEDITOR.config.toolbar = 'Basic';
CKEDITOR.config.width=400;
CKEDITOR.config.height=300;
CKEDITOR.replace('editor', CKEDITOR.config);
}
The replace command concerns me since I can't see it working, as to if the data within the editor will go away but either way nothing is happening when I click the button that runs this function.
Is this the best method, or is there a way I can do this within CKEditor directly?
Update
function toolbarSwap(){
var editor = CKEDITOR.instances['editor'];
if (editor) { editor.destroy(true); }
CKEDITOR.config.toolbar_Basic = [['Bold','Italic','Underline',
'-','JustifyLeft','JustifyCenter','JustifyRight','-','Undo','Redo']];
CKEDITOR.config.toolbar = 'Basic';
CKEDITOR.config.width=400;
CKEDITOR.config.height=300;
CKEDITOR.replace('editor', CKEDITOR.config);
}
It seems like modified the instantiation of editor with the ID resolves the issue of it finding it, but the Editor is being emptied every time I click it. Is there a way to reload the config, instead of destroying the instance?
Update 2
function changeToolBar() {
var expanded = true;
if (expanded === true) {
var myToolBar = [{ name: 'verticalCustomToolbar', groups: [ 'basicstyles'], items: [ 'Bold', 'Italic'] }];
var config = {};
config.toolbar = myToolBar;
CKEDITOR.instances.editor.destroy();//destroy the existing editor
CKEDITOR.replace('editor', config);
expanded = false;
} else {
CKEDITOR.instances.editor.destroy();//destroy the existing editor
CKEDITOR.replace('editor', {toolbar: 'Full'});
expanded = true;
console.log("Expand me")
};
}
Here is where I'm at so far. I am not losing the data during the re-init, but I am unable to ever get the 'else' statement to trigger.
My Function was correct, but the var being initialized -in- the function was resetting it's purpose everything. AKA It's -always- true on click
<button type="button" onclick="changeToolBar()">Swap It</button>
function changeToolBar() {
if (expanded === true) {
var myToolBar = [{ name: 'verticalCustomToolbar', groups: [ 'basicstyles'], items: [ 'Bold', 'Italic'] }]; //Generic placeholder
var config = {};
config.toolbar = myToolBar;
CKEDITOR.instances.editor.destroy();//destroy the existing editor
CKEDITOR.replace('editor', config);
console.log(expanded); // Logging to ensure change
expanded = false;
console.log(expanded); // Logging to ensure the change
} else {
CKEDITOR.instances.editor.destroy();//destroy the existing editor
CKEDITOR.replace('editor', {toolbar: 'Full'}); // Toolbar 'full' is a default one
expanded = true;
console.log("Expand me") // Logging if it works
};
}
Can also swap in Full with a predefined config for toolbars.

doc.addEventListener is not a function

On my page I'm rendering a tree based on jsTree angular directive. I'm trying to achieve a showing tooltip on hover for particularly node which has a description field. I have checked list of API for jsTree and have found on hover event listener hover_node, with help angular directive for jsTree I have setup my scope function to this listener
<js-tree
tree-data="scope"
tree-model="tree"
tree-events="hover_node:nodeHovered"
tree-core="tree_core"
></js-tree>
$scope.nodeHovered = function (e, data) {
var dataNode = data.node;
var original = dataNode.original;
if (typeof original.description !== 'undefined'){
var nodeDescription = original.description;
$(original).tooltip({
title: nodeDescription,
animation: true
});
}
};
My function works well when I hover on any node, I can see the object data in console, so I wrote a piece of code which allows to see the description in console if typeof node description is not an equal undefined. It works well for console but when I added function bootstrap tooltip for this node that to show the description as tooltip, I've got next error
Uncaught TypeError: doc.addEventListener is not a function
As I could understand from some topics here, the nature of this mistake is arrays don't have addEventListener function, but I'm working with an object which is already defined thru the library, so could anybody help to find what I'm missing? I appreciate any help.
Plunker
my full code
var treeFolders = [];
$scope.tree = [];
$http.get("folders.json")
.then(function (res) {
treeFolders = res.data;
angular.forEach(treeFolders, function(obj){
if(!("parent" in obj)){
obj.parent = "#";
}
})
})
$scope.load = function(){
$scope.tree = treeFolders
};
$scope.tree_core = {
multiple: false, // disable multiple node selection
check_callback: function (operation, node, node_parent, node_position, more) {
return true; // allow all other operations
},
themes : {
theme : "default",
dots : true,
icons : true
}
};
$scope.nodeHovered = function (e, data) {
var dataNode = data.node;
var original = dataNode.original;
if (typeof original.description !== 'undefined'){
var nodeDescription = original.description;
$(original).tooltip({
title: nodeDescription,
animation: true
});
}
};
html
<button class="btn btn-default" ng-click="load()">Load Tree</button>
<js-tree
tree-data="scope"
tree-model="tree"
tree-events="hover_node:nodeHovered"
tree-core="tree_core"
></js-tree>
This is because the original object that you are passing to jQuery in the following code is a jsTree node, not a DOM element:
$(original).tooltip({
title: nodeDescription,
animation: true
});
Instead use the get_node method of jsTree to retrieve the jQuery wrapped DOM element from the node:
var liElement = data.instance.get_node(data.node, true);
This will give you the entire li element, but you probably want the tooltip placed relative to the a element:
var aElement = liElement.children('a').first();
Then:
aElement.tooltip({
title: nodeDescription,
animation: true
}).tooltip('show');
Note that I have added an extra call to tooltip at the end. This is for the tooltip to be shown the first time the element is hovered. Without this the tooltip would be created on the first hover, then not shown until the next.
Demo: https://plnkr.co/edit/itMSrsroTVswD3RLbs7O?p=preview

Kendo UI Web - MultiSelect: select an option more than once

I'm currently facing a problem with the Kendo UI MultiSelect widget for selecting an option more than once. For example, in the image below I want to select Schindler's List again after selecting The Dark Knight, but unfortunately the MultiSelect widget behaves more like a set than an ordered list, i.e. repetitive selection is not allowed. Is there actually a proper way to achieve this? Any workarounds?
That's the intended behavior of the multi-select control and there is no simple way to make it do what you want using the available configuration options. Possible workarounds are ...
Creating a custom multi-select widget
Something like this should work (note that I haven't tested this much - it lets you add multiples and keeps the filter intact though):
(function ($) {
var ui = kendo.ui,
MultiSelect = ui.MultiSelect;
var originalRender = MultiSelect.fn._render;
var originalSelected = MultiSelect.fn._selected;
var CustomMultiSelect = MultiSelect.extend({
init: function (element, options) {
var that = this;
MultiSelect.fn.init.call(that, element, options);
},
options: {
name: 'CustomMultiSelect'
},
_select: function (li) {
var that = this,
values = that._values,
dataItem,
idx;
if (!that._allowSelection()) {
return;
}
if (!isNaN(li)) {
idx = li;
} else {
idx = li.data("idx");
}
that.element[0].children[idx].selected = true;
dataItem = that.dataSource.view()[idx];
that.tagList.append(that.tagTemplate(dataItem));
that._dataItems.push(dataItem);
values.push(that._dataValue(dataItem));
that.currentTag(null);
that._placeholder();
if (that._state === "filter") {
that._state = "accept";
}
console.log(this.dataSource.view());
},
_render: function (data) {
// swapping out this._selected keeps filtering functional
this._selected = dummy;
return originalRender.call(this, data);
this._selected = originalSelected;
}
});
function dummy() { return null; }
ui.plugin(CustomMultiSelect);
})(jQuery);
Demo here.
Using a dropdown list
Use a simple dropdown list (or ComboBox) and bind the select event to append to your list (which you have to create manually).
For example:
var mySelectedList = [];
$("#dropdownlist").kendoDropDownList({
select: function (e) {
var item = e.item;
var text = item.text();
// store your selected item in the list
mySelectedList.push({
text: text
});
// update the displayed list
$("#myOrderedList").append("<li>" + text + "</li>");
}
});
Then you could bind clicks on those list elements to remove elements from the list. The disadvantage of that is that it requires more work to make it look "pretty" (you have to create and combine your own HTML, css, images etc.).

WinJS.UI.ListView - refreshing items when using template is built using javascript

I've got a ListView that was using HTML-defined templates like this:
<div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template">
<div>
<!-- Displays the "picture" field. -->
<img data-win-bind="alt: title; src: picture" />
<div>
<!-- Displays the "title" field. -->
<h4 data-win-bind="innerText: title"></h4>
<!-- Displays the "text" field. -->
<h6 data-win-bind="innerText: description"></h6>
</div>
</div>
</div>
<div id="basicListView" data-win-control="WinJS.UI.ListView"
data-win-options="{itemDataSource : DataExample.itemList.dataSource, itemTemplate: select('#mediumListIconTextTemplate')}">
</div>
When my list items changed, my item template would be updated to reflect the change. However, out of need, I had to change to using a javaScript function to build my template. I modeled my code after the code found on the sample site:
app.onactivated = function (args) {
if (args.detail.kind === activation.ActivationKind.launch) {
if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
// TODO: This application has been newly launched. Initialize
// your application here.
} else {
// TODO: This application has been reactivated from suspension.
// Restore application state here.
}
args.setPromise(WinJS.UI.processAll().then(function () {
var lView = document.getElementById("templateFunctionListView").winControl;
lView.itemTemplate = itemTemplateFunction;
}));
}
};
function itemTemplateFunction(itemPromise) {
return itemPromise.then(function (item) {
var div = document.createElement("div");
var img = document.createElement("img");
img.src = item.data.picture;
img.alt = item.data.title;
div.appendChild(img);
var childDiv = document.createElement("div");
var title = document.createElement("h4");
title.innerText = item.data.title;
childDiv.appendChild(title);
var desc = document.createElement("h6");
desc.innerText = item.data.text;
childDiv.appendChild(desc);
div.appendChild(childDiv);
return div;
});
};
After changing to the javascript function, my display items never change when my binding data changes.
What do I need to do to make them update?
I think there are two approaches that could work for you.
In my case, when I refresh the data for my app, it's possible that one or more entities may be completely out of date, and there may be new entities to display. So I simply re-set the binding of the ListView, like so:
listView.itemDataSource = Data.items.dataSource;
where Data is the namespace I set up in data.js to contain all my data functions and objects.
When I update the value of the itemDataSource property, the ListView will re-bind to the new data, and display the correct items.
The other thing to look at, if your data is only being updated one property at a time, is using the WinJS.Binding.as function to make the items in the binding list observable, as described here:
http://msdn.microsoft.com/en-us/library/windows/apps/hh781224.aspx#updating_changing_records
If you haven't seen it already, there's some good info on databinding here:
http://msdn.microsoft.com/en-us/library/windows/apps/hh758311.aspx
And I found the following MSDN forum thread that may be helpful:
http://social.msdn.microsoft.com/Forums/en-US/winappswithhtml5/thread/21b9603f-e28d-4c93-b164-a2c91ba5c4ca
Hope the above helps!
For more information on Windows Store app development, register for App Builder.
Instead of rebinding the whole data set you can just rebind the single item. Find the items position in the list and then splice it replacing it with itself.
for (var i = 0; i < list.length; i++){
item = list.getAt(i);
if (item.key == itemToBeReBound.key){
list.splice(i, 1, item);
i = list.length;
}
}

Backbone Copy One Views Events to Another

I have this view in Backbone that changes its events depending on a users action.
So I have three views, all have been initialized.
var view1 = new MainView({el : '#view1'});
var view2 = new ProductsView({el : '#prodcuts'});
var view3 = new StoresView({el : '#stores'});
Now what I want to do is copy events from one view to another and then updating the views el. I've tried:
if($option == 'products') {
view1.events = view2.events
$("div[data-role='content']", view1.el).html(content);
} else {
view1.events = view3.events
$("div[data-role='content']", view1.el).html(content);
}
The problem is that even now the content is the same, and the elements are there that correspond with the events BUT the events are no longer firing. Why is this and how can I fix it?
You need to call the delegateEvents method.
For example something like the following (given the code you provided).
if($option == 'products') {
view1.delegateEvents(view2.events)
$("div[data-role='content']", view1.el).html(content);
} else {
view1.delegateEvents(view3.events);
$("div[data-role='content']", view1.el).html(content);
}
Also note that for removing events you use the undelegateEvents() method.

Categories

Resources