WinJS.UI.ListView not working in snapped view - javascript

I am using a WinJS.UI.ListView in a JavaScript project for Windows-8 Metro interface.
This is the HTML code:
<div id="myMain">
<div id="myListTemplate" data-win-control="WinJS.Binding.Template">
<div class="myListViewItem">
<p data-win-bind="innerText: description"></p>
</div>
</div>
<div id="myListView"
data-win-control="WinJS.UI.ListView"
data-win-options="{ itemTemplate: myTemplate, layout: {type: WinJS.UI.ListLayout} }">
</div>
</div>
And part of the JavaScript:
ready: function (element, options) {
// Set up the ListView.
var myLView = myListView.winControl;
WinJS.UI.setOptions(favoritesLView, {
itemDataSource: dataSource,
oniteminvoked: this.onItemInvoked.bind(this),
selectionMode: WinJS.UI.SelectionMode.none
});
},
Where dataSource is where the list information is stored. It is a list obtained from:
var myList = new WinJS.Binding.List(myJSONarray);
The code is working in landscape and portrait view, but doesn't work when in snapped view. The list view appears empty despite myList has all the elements.
Is this a bug in Windows 8? Anybody know of a workaround to solve it?
I have found this link with the same problem but its solution doesn't work for me:
http://social.msdn.microsoft.com/Forums/pl-PL/winappswithhtml5/thread/ce8c722d-526b-4226-9e40-642ddb37422b

One reason that the ListView will not be displayed is if the element or any parent elements' display is set to "none". When the element becomes visible again, you will need to call listView.forceLayout(). See the explanation below from MSDN, http://msdn.microsoft.com/en-us/library/windows/apps/hh758352.aspx
When you set the style.display property of a ListView or its parent
elements to "none", the app discards layout information about those
elements. When you change the value of the display property back to a
style that makes everything visible again, the app will layout all the
elements, but the ListView won't receive information about the current
layout and will have an invalid layout. You can fix the issue by
calling this function when you make the ListView visible again.

Related

Accordion closing onClick anywhere in container

I am trying to create an accordion for a project I'm working on. For the sake of argument, lets assume this accordion only has one container. So far, I've got it all working, however when I expand the accordion, which will only expend if I click on the header, I am then able to close the open container by clicking anywhere in the container, rather than just the header.
I've tried a few different things resulting in null .toggle errors so far. Below is a snippet of the accordion itself, along with the JS I'm using with it. Please bare in mind the accordion functions correctly and displays correctly, its the click function that's the issue (meaning my CSS is fine so no point sharing):
JS:
const accordion = document.getElementsByClassName('container1');
for (i=0; i<accordion.length; i++) {
accordion[i].addEventListener('click', function () {
this.classList.toggle('active');
});
}
Accordion HTML:
<div class="accordion-body">
<div class="accordion">
<hr>
<div class="container1" id="container1">
<div class="label" id="linkId">Generate a payment link</div>
<div class="content">
<div class="form">
</div>
</div>
</div>
<hr>
</div>
</div>
Essentially, I only even want the accordion to open/close if the 'label' div is pressed. This is because within my accordion there are buttons, so at the moment when a button is pressed when accordion is open, it changes the class which closes the accordion back up. Right now I understand that the clickable area is 'container1' but I've not been able to make it work against the label div.
I can also provide a link to the webpage where it is happening, happy to provide this via PM.
I tried changing the JS to the below:
const accordion = document.getElementsByClassName('container1');
const linkId = document.getElementById('linkId');
for (i=0; i<accordion.length; i++) {
document.getElementById('linkId').addEventListener('click', function () {
accordion.classList.toggle('active');
});
}
However the above produces the following error:
Uncaught TypeError: Cannot read properties of undefined (reading 'toggle')
at HTMLDivElement. (txninfo.php:825:25)
LINE 825 is the following:
accordion.classList.toggle('active');
Any help would be massively appreciated
accordion in that case is instance of HTML-Collection and not Element as you assume.
So you correctly iterate over the collection of elements, you now just want to select the current element (where key == i) of iteration instead of the whole collection.
accordion[i].classList.toggle('active');
then you should have an Element and should be able to access it´s properties like classList
https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName

Combining Waypoints and Horizontal Scroll

I have been successful in getting Waypoints (http://imakewebthings.com/jquery-waypoints/) and a horizontal scroll (http://www.htmldrive.net/items/show/966/jQuery-Horizontal-automatic-Scrollbars-with-mouse) working on separate pages, but cannot combine them. I think it has something to do with the waypoints option parameters.
The waypoints function is:
$(function () {
$('#waypoint').waypoint(function () {
alert('You have scrolled to an entry.');
}, {
offset: '100px'
});
});
Its added to the page with:
<div id="horiz_container_outer">
<div id="horiz_container_inner">
<div id="horiz_container">
<div class="horiz_box1">Stuff</div>
<div class="horiz_box2">Stuff</div>
<div class="horiz_box1">Stuff2</div>
<div class="horiz_box2">Stuff2</div>
<div class="horiz_box1">Stuff3</div>
<div class="horiz_box2">Stuff3</div>
<div id="waypoint">Waypoint</div>
</div>
</div>
I put together a quick JS fiddle, but the horizontal slider was not working in that example for some reason. IF it helps: http://jsfiddle.net/bretwhiteley/w2p84Lmp/
In addition to the horizontal option, you need to set the context option since the scrollable element you're using isn't the window. From the docs:
The context defines which scrollable element the waypoint belongs to and acts within. The default, window, means the waypoint offset is calculated with relation to the whole viewport. You can set this to another element to use the waypoints within that element. It accepts a selector string, raw HTML element, or jQuery object.
Update: The 3.0 release brings is a new doc page for the context option and changes the rules slightly about what is allowed depending on which build you're using.

Performing actions on element with non-unique class name

--Before I begin, I should say I'm trying to accomplish this with no libraries. Sorry jQuery--
In a general sense, I'm wondering the best way to use event listeners on a list when no item in the list has a unique classname or id. More specifically, I have this:
Currently, I have a WinJS listView that is data-bound like in this guide. As you can see, no item in the list has a unique element id or classname. This is causing me an issue because I want to add a click listener to each one, so that when you click a certain item in the list, this behavior happens (as shown in the gif). I need a sub menu to appear underneath the item in the list that corresponds to the appropriate item in the list.
This would be easy enough if they all had unique ids and/or classnames. But since they don't, I was thinking when somebody clicks on an item, you have to get which one it is and then add a classname to all the items in the list beneath the one you clicked so that you can move them down using the WinJS .createExpandAnimation function. Then once the submenu has been closed, strip off all of the added classnames. Is that really the best way to do it?
I'm open to completely removing the listView, but I'd like a way to data-bind in a similar fashion. Is there a way to do this not using the listView (or another library) that would make life easier?
Edit:
My code is in an identical format to this that Microsoft provides in their walkthrough.
<div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template">
<div style="width: 150px; height: 100px;">
<!-- Displays the "picture" field. -->
<img src="#" style="width: 60px; height: 60px;"
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: text"></h6>
</div>
</div>
</div>
<div id="basicListView" data-win-control="WinJS.UI.ListView"
data-win-options="{itemDataSource : DataExample.itemList.dataSource,
itemTemplate: select('#mediumListIconTextTemplate')}">
</div>
where dataSource is defined like this:
(function () {
"use strict";
var dataArray = [
{ title: "Basic banana", text: "Low-fat frozen yogurt", picture: "images/60banana.png" },
{ title: "Banana blast", text: "Ice cream", picture: "images/60banana.png" }
];
var dataList = new WinJS.Binding.List(dataArray);
// Create a namespace to make the data publicly
// accessible.
var publicMembers =
{
itemList: dataList
};
WinJS.Namespace.define("DataExample", publicMembers);
Honestly, I'm not even sure this will work with a WinJS listView, so I may have to change this entirely to use an html list or something like that.
You can use the oniteminvoked event (http://msdn.microsoft.com/en-us/library/windows/apps/br211827.aspx) to handle the click of a ListView item, and the clicked item will be avaialble in the event handler's parameter.
What you do with that value is up to you. Use it to insert an item in the ListView, use it to show a hidden element in the invoked item, etc.

knockout.js visibility not working when css style is applied

I have an issue where knockout.js 2.0 isn't showing my item when a CSS style is applied to it. It won't update the display with the style applied to it. If it is off it works.
CSS
.success { display:none }
HTML
<div data-bind="visible: site.signUp.success()" class="success">
Thanks for signining up. You will recieve an email from us in the near future.
</div>
JS
app.viewModel.site.signUp.success(true);
In the period of time before Knockout.js applies bindings, you can prevent the initial rendering/flashing effect by setting the default display style to none.
<div style="display: none" data-bind="visible: site.signUp.success">
Thanks for signining up. You will recieve an email from us in the near future.
</div>
I created a fiddle that shows how you can use the css binding in Knockout to do this. http://jsfiddle.net/johnpapa/vwcfT/
Here is the HTML:
Success Flag: <input type="checkbox" data-bind="checked:site.signUp.success"></input>
<div data-bind="visible: site.signUp.success" >
Thanks for signining up. You will recieve an email from us in the near future.
</div>
<br/><br/>
<span data-bind="text:site.signUp.success"></span>
<div data-bind="css: { success: site.signUp.success}" >
Thanks for signining up. You will recieve an email from us in the near future.
</div>
The first DIV in the example just uses the visible binding, since you dont really need a css class to do this. The second DIV in the example binds to a css class named "success" if the site.signUp.success observable is true. This is more verbose than the first, but could be useful if you needed your css class to do more than just set visibility.
Hope this helps.
Here is the javascript:
var viewModel = {
site: {
signUp: {
success: ko.observable(true)
}
}
};
ko.applyBindings(viewModel);
That's because the success style is defined as display:none, which is equivalent to visible = false. Your CSS class is cancelling out your site.signUp.success() call.
If you want your DIV to show up only when site.signUp.success() == true, just do this:
<div data-bind="visible: site.signUp.success">
Thanks for signining up. You will recieve an email from us in the near future.
</div>
It might be a bit late but I found the following useful. Instead of fixing every element with a visibility control, just wrap a div around all your pre-hidden elements as follow:
<div style="display:none" data-bind="visible: true">
Some pre-hidden elements
<div data-bind="visible: myVisibleFoo">...</div>
<div data-bind="visible: myVisibleBar">...</div>
Other pre-hidden elements
...
</div>
The whole section of elements is hidden initially and is only shown after KO has applied bindings. I usually wrap the whole page with it to avoid any flashing problem.
Just run into this myself; I can see why the did it this way, but it is handy to set a default visibility of none on late loaded elements on the page so they don't flash as scripts are loaded. The nicest way I could find of doing this was just to create a simple custom binding:
ko.bindingHandlers.forceVisible = {
update:
function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext)
{
if(ko.unwrap(f_valueaccessor()))
el.style.display = 'inherit';
else
el.style.display = 'none';
}
};
You have to be a little bit careful when setting up your styles; if you are using a div and your CSS sets it to display:inline-block then this code will not work - it will have block display when the inherit is applied. This simple solution was fine for my use case, however.

TinyMCE Remove DIVs with a specific class

I would like to remove a div from the TinyMCE editor content that has a specific class.
In the ideal world I'd like to be able to do this via the valid_elements option but I don't know if it's achievable.
Here is a sample of editor content:
<div class="content">
Some html content here
<div class="anotherclass"></div>
</div>
I would like the
<div class="content">
stripping out so the editor will only show this:
Some html content here
<div class="anotherclass"></div>
Cheers guys.
First get the innerHTML of the div, and then append that content to the div, after which you can remove it.
In jQuery:
var contentHtml = $(".content").html();
$(".content").after(contentHtml);
$(".content").remove();
Of course, if you have multiple divs with these classes its more complicated because then you would have to work with parents etc.
Problem here will that by default your editor will have a root_block element (in your case div) and all content gets wrapped inside that kind of root_block element. This is done for styling purposes, but can be deactivated using this initialization params
force_p_newlines : false,
force_br_newlines : false,
convert_newlines_to_brs : false,
remove_linebreaks : true,
Once that is done you can use this code to easily get rid tof your divs.
var $elements_to_be_removed = $(".content");
$elements_to_be_removed.each(function(index) {
$(this).replaceWith(this.innerHTML);
});

Categories