The first hurdle is that our control doesn’t actually scroll. Since we know that there are 30 groups on our control we should be able to scroll down to get to the other items. Go back to the iOSTableView.SetupCSS and add this code just below the first two lines to tell the control to scroll in the Y direction when it overflows:
styles(0).value("visibility") = "visible" styles(0).Value("background-color") = "#FFFFFF" styles(0).Value("overflow-y") = "scroll"
If you run the project now, you’ll find that on the desktop it scrolls very nicely. If you’re using a Mac with a trackpad and a recent version of OS X, you even get kinetic scrolling for free. Now try connecting from an iOS device (the iOS simulator will work too). Neat huh? Scrolling “works” except that there’s no kinetic scrolling. We need to add one more style to enable that:
styles(0).value("visibility") = "visible" styles(0).Value("background-color") = "#FFFFFF" styles(0).Value("overflow-y") = "scroll" styles(0).Value("-webkit-overflow-scrolling") = "touch"
There we go. Now the scrolling behavior acts right on the iOS devices as well (Android too if you’re curious).
Now that we’ve got scrolling working, have you ever noticed the effect on an iOSTableView where the headers stick to the top of the screen until the one below it bumps up against it? Apple added an attribute so we can simulate that effect. In the code for the headers, you need to add a value for position like this:
dim st as new WebControlCSSst.Selector = ".iOSTableView_header" st.Value("padding") = "5px" st.Value("background-color") = "rgba(240,240,240,0.9)" st.Value("top") = "0px" st.Value("position") = "-webkit-sticky" styles.Append st
This effect also relies on the headers being “pulled” up by their containing element. At the moment, that’s the entire control, so we’ll need to add another div around each group. In iOSTableViewGroup.Render, add the following lines:
dim sa() as string sa.Append "<div>" sa.Append "<div class=""iOSTableView_header"">" + self.Caption + "</div>" sa.Append "<ul>" for i as integer = 0 to UBound(items) sa.Append items(i).Render() next i sa.Append "</ul>" sa.Append "</div>" return join(sa, EndOfLine)
If you run the project now, the date headers will actually stick to the top of the view until the next one comes along! We’re not out of the woods yet though. There’s still that nasty issue of what happens if you pull downward first, because it acts like you’re pulling the whole web page down with it… and in fact, you are.
So let’s add a second div inside the outer control div. In iOSTableView.SetupHTML:
dim sa() as string sa.Append "<div id=""" + self.ControlID + """ class=""iOSTableView"">" sa.append "<div class=""iOSTableView_scrollarea"">" for i as integer = 0 to UBound(groups) sa.Append groups(i).Render() next sa.Append "</div>" sa.Append "</div>" return join(sa, EndOfLine)
Now a little CSS magic. In iOSTableView.SetupCSS, only add the overflow-y and -webkit-overflow-scrolling properties if the browser is SafariMobile or Android. If we don’t do this, the desktop browsers will get double scrollbars:
styles(0).value("visibility") = "visible" styles(0).Value("background-color") = "#FFFFFF" select case session.Browser case websession.BrowserType.SafariMobile, websession.BrowserType.Android styles(0).Value("overflow-y") = "scroll" styles(0).Value("-webkit-overflow-scrolling") = "touch" end select
Then add another style definition to the event:
st = new WebControlCSS st.Selector = ".iOSTableView_scrollarea" st.Value("overflow-y") = "scroll" st.Value("-webkit-overflow-scrolling") = "touch" st.Value("width") = "100%" st.Value("height") = "100%" styles.Append st
Run the project again and check it on the desktop and mobile devices. Now if the user starts by dragging downward, only the control scrolls!
This control is useless if you can’t tell which rows the user has touched. We’ve still got a few last pieces to add to make this work.
Go back to the iOSTableView class and add an event handler for ExecuteEvent (if you haven’t already). We need to make it so the control can handle an event coming from the browser. Enter the following code:
select case Name case "rowclicked" RaiseEvent RowClicked(parameters(0)) end select
…and add the event definition for the event that we’re raising…
Event RowClicked(tag as Variant)
So what we’re going to do is add links to each of the rows. This brings up an interesting flaw in our original design. The innermost items, where the actual links are going to be called, has no idea about the Control ID of the control which contains it. We need to send that data down through the control at render time. In iOSTableViewItem.Render, add a parameter: ParentControlID as String. Then add these two rows to the method:
Now we go up one level to iOSTableViewGroup and make it so we can pass along the ParentControlID parameter. Add a parameter to iOSTableViewGroup.Render: ParentControlID as String. Then add the parameter to the call to render the child nodes:
Add the Control ID to the call to the group’s Render method in iOSTableView.SetupHTML:
Last but not least, we need to add a little more code to SetupCSS to keep the links from changing color:
st = new WebControlCSS st.Selector = ".iOSTableView ul li.iOSTableViewRow a" st.Value("color") = "#000" st.Value("text-decoration") = "none" styles.Append st
Now go back to WebPage1, add a Label to the layout and then implement the RowClicked event on the iOSTableView Instance. If you set the code to something like this:
Label1.Text = "Item " + Str(Tag.IntegerValue)
When you run the project, clicking or touching the rows will change the label based on the row.
Well, that’s it! Now you have a fully functional iOSTableView which you can use in your projects which looks and feels like a native control.