WebSharper JQuery Mobile Page Hidden

2019-07-02 01:04发布

I'm trying to put together a JQuery Mobile site using the F# WebSharper Framework. In WebSharper parlance I have created a Pagelet using JQueryMObile controls which is being served by a Sitelet. Everything compiles and runs, the problem is in the html that is generated.

The page I have declared (simplePage) clearly exists in the markup and is marked with the JQueryMobile css class ui-active to make it visible. However, it is surrounded by a div that is also a page but is not marked with the active css class, making it invisible. Therefore my page inside this div is hidden. I am not creating this containing page div. It seems to be a side-affect of loading the JQueryMobile script in the html head. How can I get rid of it?

I have taken the example from http://websharper.com/samples/JQueryMobile. I am using WebSharper version 2.5.125.62 and WebSharper.JQueryMobile version 2.5.4.198. I have one relevant code file shown below followed by the generated html.

Main:

open IntelliFactory.Html
open IntelliFactory.WebSharper
open IntelliFactory.WebSharper.Html
open IntelliFactory.WebSharper.JQuery
open IntelliFactory.WebSharper.Sitelets

type Action = | Home

[<JavaScript>]
module MyJQueryContent =

    let Main() =
        JQuery.Mobile.Mobile.Use()
        let page = Div [
                        Id "simplePage"
                        HTML5.Attr.Data "role" "page"
                        HTML5.Attr.Data "url" "#simplePage"
                        ] -< [
                        Div[Text "content"]
                    ]
        Div [page]
        |>! OnAfterRender (fun _ -> JQuery.Of(page.Body)
                                    |> JQuery.Mobile.JQuery.Page
                                    |> ignore

                                    JQuery.Mobile.Mobile.Instance.ChangePage(JQuery.Of(page.Body)))

[<Sealed>]
type MyJQueryMobileEntryPoint() =
    inherit Web.Control()

    [<JavaScript>]
    override this.Body = MyJQueryContent.Main() :> _

module Pages =

    let HomePage =
        PageContent <| fun context ->
            { Page.Default with
                Title = Some "Index"
                Body = [IntelliFactory.Html.Tags.Div[new MyJQueryMobileEntryPoint()]] }

[<Sealed>]
type Website() =
    interface IWebsite<Action> with
        member this.Sitelet = Sitelet.Content "/" Home Pages.HomePage
        member this.Actions = [Home]

type Global() =
    inherit System.Web.HttpApplication()

    member g.Application_Start(sender: obj, args: System.EventArgs) =
        ()

[<assembly: Website(typeof<Website>)>]
do ()

Output:

html output

3条回答
成全新的幸福
2楼-- · 2019-07-02 01:47

As a side note, you are creating one of the containing DIVs when you write Div [page] instead of page before adding OnAfterRender, but indeed this is not your problem.

As Omar describes, with jQuery Mobile you need to carefully control when and how the initialization of the page structure takes place, especially when working with dynamic pages. I recall seeing your exact problem before but I can't find that conversation in my email box, however, here is an earlier article that has some useful bits for tapping into JQM page initialization:

http://fpish.net/blog/JankoA/id/3362/201367-jquery-mobile-page-reuse-with-websharper

查看更多
Rolldiameter
3楼-- · 2019-07-02 01:55

I am a developer of WebSharper. Omar is right, this is a JQM thing, another workaround for it is having a dummy page node in the sitelet. Like this:

module Pages =
    open IntelliFactory.Html

    let HomePage =
        PageContent <| fun context ->
            { Page.Default with
                Title = Some "Index"
                Body = 
                    [
                        Div [HTML5.Data "role" "page"; Id "dummy"]
                        Div [new MyJQueryMobileEntryPoint()]
                    ] }
查看更多
时光不老,我们不散
4楼-- · 2019-07-02 02:03

When jQuery Mobile framework is loaded, it checks if there is a page div in DOM. If not, it wraps body's content in page div. To control this behavior, you need to prevent jQM's autoInitializePage in order to initialize manually $.mobile.initializePage() whenever you want.

You need to listen to mobileinit event to override autoInitializePage. The code should be placed after jQuery (core) and before jQuery Mobile libraries in head.

/* jQuery.js */
$(document).on("mobileinit", function () {
  $.mobile.autoInitializePage = false;
});
/* jQuery-Mobile.js */

Now you can initialize jQuery Mobile whenever you want by calling $.mobile.initializePage().

查看更多
登录 后发表回答