Javascript jQuery Mobile:动态添加内容的标记增强

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14550396/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 17:10:37  来源:igfitidea点击:

jQuery Mobile: Markup Enhancement of dynamically added content

javascriptjqueryhtmlcordovajquery-mobile

提问by user2001897

I was wondering how can I enhance dynamically jQuery Mobile page?

我想知道如何动态增强 jQuery Mobile 页面?

I have tried to use these methods:

我曾尝试使用这些方法:

  1. $('[data-role="page"]').trigger('create');

    and

  2. $('[data-role="page"]').page();

  1. $('[data-role="page"]').trigger('create');

  2. $('[data-role="page"]').page();

Also how can I prevent enhancement markup of check boxes only?

另外,如何仅防止复选框的增强标记?

回答by Gajotres

Disclaimer:

免责声明:

This article can also be found as a part of my blog HERE.

这篇文章也可以作为我博客的一部分在这里找到

Intro:

介绍:

There are several ways of enhancing dynamically created content markup. It is just not enough to dynamically add new content to jQuery Mobilepage, new content must be enhanced with classic jQuery Mobilestyling. Because this is rather processing heavy task there need to be some priorities, if possible jQuery Mobileneeds to do as less enhancing as possible. Don't enhance whole page if only one component need's to be styled.

有多种方法可以增强动态创建的内容标记。仅将新内容动态添加到jQuery Mobile页面是不够的,必须使用经典的jQuery Mobile样式来增强新内容。因为这是处理繁重的任务,所以需要有一些优先级,如果可能的话,jQuery Mobile需要做尽可能少的增强。如果只需要设置一个组件的样式,则不要增强整个页面。

What does this all means? When page plugin dispatches a pageInitevent, which most widgets use to auto-initialize themselves. it will automatically enhance any instances of the widgets it finds on the page.

这一切意味着什么?当页面插件调度pageInit事件时,大多数小部件使用它来自动初始化自己。它将自动增强它在页面上找到的小部件的任何实例。

However, if you generate new markup client-side or load in content via Ajax and inject it into a page, you can trigger the create event to handle the auto-initialization for all the plugins contained within the new markup. This can be triggered on any element (even the page div itself), saving you the task of manually initializing each plugin (listview button, select, etc.).

但是,如果您在客户端生成新标记或通过 Ajax 加载内容并将其注入页面,则可以触发 create 事件来处理新标记中包含的所有插件的自动初始化。这可以在任何元素(甚至页面 div 本身)上触发,从而为您省去手动初始化每个插件(列表视图按钮、选择等)的任务。

With this in mind lets discuss enhancement levels. There are three of them and they are sorted from the less resource demanding to higher ones:

考虑到这一点,让我们讨论增强级别。其中有三个,它们从资源需求较低的到较高的排序:

  1. Enhance a single component/widget
  2. Enhance a page content
  3. Enhance a full page content (header, content, footer)
  1. 增强单个组件/小部件
  2. 增强页面内容
  3. 增强整页内容(页眉、内容、页脚)

Enhance a single component/widget:

增强单个组件/小部件:

Important:The below enhancement methods are to be used only on current/active page. For dynamically inserted pages, those pages and their contents will be enhanced once inserted into DOM. Calling any method on dynamically created pages / other than the active page, will result an error.

重要提示:以下增强方法仅用于当前/活动页面。对于动态插入的页面,这些页面及其内容一旦插入到 DOM 中就会得到增强。在动态创建的页面/非活动页面上调用任何方法都会导致错误。

Every jQuery Mobilewidget can be enhanced dynamically:

每个jQuery Mobile小部件都可以动态增强:

  1. Listview:

    Markup enhancement:

    $('#mylist').listview('refresh');
    

    Removing listview elements:

    $('#mylist li').eq(0).addClass('ui-screen-hidden'); 
    

    Enhancement example: http://jsfiddle.net/Gajotres/LrAyE/

    Note that the refresh() method only affects new nodes appended to a list. This is done for performance reasons.

    One of a listview high-points is a filtering functionality. Unfortunately, for some reason, jQuery Mobile will fail to dynamically add filter option to an existing listview. Fortunately there's a workaround. If possible, remove current listview and add another one with a filer option turned on.

    Here's a working example: https://stackoverflow.com/a/15163984/1848600

    $(document).on('pagebeforeshow', '#index', function(){       
        $('<ul>').attr({'id':'test-listview','data-role':'listview', 'data-filter':'true','data-filter-placeholder':'Search...'}).appendTo('#index [data-role="content"]');
        $('<li>').append('<a href="#">Audi</a>').appendTo('#test-listview');
        $('<li>').append('<a href="#">Mercedes</a>').appendTo('#test-listview');
        $('<li>').append('<a href="#">Opel</a>').appendTo('#test-listview');
        $('#test-listview').listview().listview('refresh');
    });
    
  2. Button

    Markup enhancement:

    $('[type="button"]').button();
    

    Enhancement example: http://jsfiddle.net/Gajotres/m4rjZ/

    One more thing, you don't need to use a input element to create a button, it can be even done with a basic div, here's an example: http://jsfiddle.net/Gajotres/L9xcN/

  3. Navbar

    Markup enhancement:

    $('[data-role="navbar"]').navbar();
    

    Enhancement example: http://jsfiddle.net/Gajotres/w4m2B/

    Here's a demo how to add dynamic navbar tab: http://jsfiddle.net/Gajotres/V6nHp/

    And one more in pagebeforecreateevent: http://jsfiddle.net/Gajotres/SJG8W/

  4. Text inputs, Search inputs & Textareas

    Markup enhancement:

    $('[type="text"]').textinput();   
    

    Enhancement example: http://jsfiddle.net/Gajotres/9UQ9k/

  5. Sliders & Flip toggle switch

    Markup enhancement:

    $('[type="range"]').slider();  
    

    Enhancement example: http://jsfiddle.net/Gajotres/caCsf/

    Enhancement example during the pagebeforecreate event: http://jsfiddle.net/Gajotres/NwMLP/

    Sliders are little bit buggy to dynamically create, read more about it here: https://stackoverflow.com/a/15708562/1848600

  6. Checkbox & Radiobox

    Markup enhancement:

    $('[type="radio"]').checkboxradio();
    

    or if you want to select/deselect another Radiobox/Checkbox element:

    $("input[type='radio']").eq(0).attr("checked",false).checkboxradio("refresh");
    

    or

    $("input[type='radio']").eq(0).attr("checked",true).checkboxradio("refresh");
    

    Enhancement example: http://jsfiddle.net/Gajotres/VAG6F/

  7. Select menu

    Markup enhancement:

    $('select').selectmenu();  
    

    Enhancement example: http://jsfiddle.net/Gajotres/dEXac/

  8. Collapsible

    Unfortunately collapsible element can't be enhanced through some specific method, so trigger('create') must be used instead.

    Enhancement example: http://jsfiddle.net/Gajotres/ck6uK/

  9. Table

    Markup enhancement:

    $(".selector").table("refresh");
    

    While this is a standard way of table enhancement, at this point I can't make it work. So instead use trigger('create').

    Enhancement example: http://jsfiddle.net/Gajotres/Zqy4n/

  10. Panels- New

    Panel Markup enhancement:

    $('.selector').trigger('pagecreate');
    

    Markup enhancement of content dynamically addedto Panel:

    $('.selector').trigger('pagecreate');
    

    Example: http://jsfiddle.net/Palestinian/PRC8W/

  1. 列表视图

    标记增强:

    $('#mylist').listview('refresh');
    

    删除列表视图元素:

    $('#mylist li').eq(0).addClass('ui-screen-hidden'); 
    

    增强示例:http: //jsfiddle.net/Gajotres/LrAyE/

    请注意,refresh() 方法仅影响附加到列表的新节点。这样做是出于性能原因。

    列表视图的亮点之一是过滤功能。不幸的是,由于某种原因,jQuery Mobile 将无法向现有列表视图动态添加过滤器选项。幸运的是,有一个解决方法。如果可能,删除当前列表视图并添加另一个打开文件管理器选项的列表视图。

    这是一个工作示例:https: //stackoverflow.com/a/15163984/1848600

    $(document).on('pagebeforeshow', '#index', function(){       
        $('<ul>').attr({'id':'test-listview','data-role':'listview', 'data-filter':'true','data-filter-placeholder':'Search...'}).appendTo('#index [data-role="content"]');
        $('<li>').append('<a href="#">Audi</a>').appendTo('#test-listview');
        $('<li>').append('<a href="#">Mercedes</a>').appendTo('#test-listview');
        $('<li>').append('<a href="#">Opel</a>').appendTo('#test-listview');
        $('#test-listview').listview().listview('refresh');
    });
    
  2. 按钮

    标记增强:

    $('[type="button"]').button();
    

    增强示例:http: //jsfiddle.net/Gajotres/m4rjZ/

    还有一件事,你不需要使用 input 元素来创建按钮,它甚至可以用一个基本的 div 来完成,这是一个例子:http: //jsfiddle.net/Gajotres/L9xcN/

  3. 导航栏

    标记增强:

    $('[data-role="navbar"]').navbar();
    

    增强示例:http: //jsfiddle.net/Gajotres/w4m2B/

    这是如何添加动态导航栏选项卡的演示:http: //jsfiddle.net/Gajotres/V6nHp/

    还有一个pagebeforecreate事件:http: //jsfiddle.net/Gajotres/SJG8W/

  4. 文本输入、搜索输入和文本区域

    标记增强:

    $('[type="text"]').textinput();   
    

    增强示例:http: //jsfiddle.net/Gajotres/9UQ9k/

  5. 滑块和翻转拨动开关

    标记增强:

    $('[type="range"]').slider();  
    

    增强示例:http: //jsfiddle.net/Gajotres/caCsf/

    pagebeforecreate 事件期间的增强示例:http: //jsfiddle.net/Gajotres/NwMLP/

    动态创建滑块有点麻烦,请在此处阅读更多相关信息:https: //stackoverflow.com/a/15708562/1848600

  6. 复选框和单选框

    标记增强:

    $('[type="radio"]').checkboxradio();
    

    或者如果您想选择/取消选择另一个 Radiobox/Checkbox 元素:

    $("input[type='radio']").eq(0).attr("checked",false).checkboxradio("refresh");
    

    或者

    $("input[type='radio']").eq(0).attr("checked",true).checkboxradio("refresh");
    

    增强示例:http: //jsfiddle.net/Gajotres/VAG6F/

  7. 选择菜单

    标记增强:

    $('select').selectmenu();  
    

    增强示例:http: //jsfiddle.net/Gajotres/dEXac/

  8. 可折叠

    不幸的是,无法通过某些特定方法增强可折叠元素,因此必须使用 trigger('create') 代替。

    增强示例:http: //jsfiddle.net/Gajotres/ck6uK/

  9. 桌子

    标记增强:

    $(".selector").table("refresh");
    

    虽然这是表增强的标准方式,但此时我无法使其工作。所以改用触发器('创建')。

    增强示例:http: //jsfiddle.net/Gajotres/Zqy4n/

  10. 面板-

    面板标记增强:

    $('.selector').trigger('pagecreate');
    

    动态添加到 Panel的内容的标记增强:

    $('.selector').trigger('pagecreate');
    

    示例:http: //jsfiddle.net/Palestinian/PRC8W/

Enhance a page content:

增强页面内容:

In case we are generating/rebuilding whole page content it is best to do it all at once and it can be done with this:

如果我们正在生成/重建整个页面内容,最好一次完成,并且可以通过以下方式完成:

$('#index').trigger('create');

Enhancement example: http://jsfiddle.net/Gajotres/426NU/

增强示例:http: //jsfiddle.net/Gajotres/426NU/

Enhance a full page content (header, content, footer):

增强整页内容(页眉、内容、页脚):

Unfortunately for us trigger('create') can not enhance header and footer markup. In that case we need big guns:

不幸的是,trigger('create') 不能增强页眉和页脚标记。在这种情况下,我们需要大枪:

$('#index').trigger('pagecreate');

Enhancement example: http://jsfiddle.net/Gajotres/DGZcr/

增强示例:http: //jsfiddle.net/Gajotres/DGZcr/

This is almost a mystic method because I can't find it in official jQuery Mobiledocumentation. Still it is easily found in jQuery Mobilebug tracker with a warning not to use it unless it is really really necessary.

这几乎是一种神秘的方法,因为我在官方jQuery Mobile文档中找不到它。它仍然很容易在jQuery Mobile错误跟踪器中找到,并警告不要使用它,除非确实有必要。

Note, .trigger('pagecreate');can suppose be used only once per page refresh, I found it to be untrue:

注意,.trigger('pagecreate'); 可以假设每次页面刷新只使用一次,我发现它是不真实的:

http://jsfiddle.net/Gajotres/5rzxJ/

http://jsfiddle.net/Gajotres/5rzxJ/

3rd party enhancement plugins

第 3 方增强插件

There are several 3rd party enhancement plugins. Some are made as an update to an existing method and some are made to fix broken jQM functionalities.

有几个 3rd 方增强插件。有些是作为对现有方法的更新,有些是为了修复损坏的 jQM 功能。

  • Button text change

    Unfortunately cant found the developer of this plugin. Original SO source: Change button text jquery mobile

    (function($) {
        /*
         * Changes the displayed text for a jquery mobile button.
         * Encapsulates the idiosyncracies of how jquery re-arranges the DOM
         * to display a button for either an <a> link or <input type="button">
         */
        $.fn.changeButtonText = function(newText) {
            return this.each(function() {
                $this = $(this);
                if( $this.is('a') ) {
                    $('span.ui-btn-text',$this).text(newText);
                    return;
                }
                if( $this.is('input') ) {
                    $this.val(newText);
                    // go up the tree
                    var ctx = $this.closest('.ui-btn');
                    $('span.ui-btn-text',ctx).text(newText);
                    return;
                }
            });
        };
    })(jQuery);
    

    Working example: http://jsfiddle.net/Gajotres/mwB22/

  • 按钮文字更改

    不幸的是找不到这个插件的开发者。原始 SO 来源:更改按钮文本 jquery mobile

    (function($) {
        /*
         * Changes the displayed text for a jquery mobile button.
         * Encapsulates the idiosyncracies of how jquery re-arranges the DOM
         * to display a button for either an <a> link or <input type="button">
         */
        $.fn.changeButtonText = function(newText) {
            return this.each(function() {
                $this = $(this);
                if( $this.is('a') ) {
                    $('span.ui-btn-text',$this).text(newText);
                    return;
                }
                if( $this.is('input') ) {
                    $this.val(newText);
                    // go up the tree
                    var ctx = $this.closest('.ui-btn');
                    $('span.ui-btn-text',ctx).text(newText);
                    return;
                }
            });
        };
    })(jQuery);
    

    工作示例:http: //jsfiddle.net/Gajotres/mwB22/

Get correct maximum content height

获取正确的最大内容高度

In case page header and footer has a constant height content div can be easily set to cover full available space with a little css trick:

如果页面页眉和页脚具有恒定高度的内容 div 可以轻松设置为使用一个小 css 技巧来覆盖全部可用空间:

#content {
    padding: 0;
    position : absolute !important; 
    top : 40px !important;  
    right : 0; 
    bottom : 40px !important;  
    left : 0 !important;     
}

And here's a working example with Google maps api3demo: http://jsfiddle.net/Gajotres/7kGdE/

这是一个带有Google maps api3演示的工作示例:http: //jsfiddle.net/Gajotres/7kGdE/

This method can be used to get correct maximum content height, and it must be used with a pageshowevent.

此方法可用于获取正确的最大内容高度,并且必须与pageshow事件一起使用。

function getRealContentHeight() {
    var header = $.mobile.activePage.find("div[data-role='header']:visible");
    var footer = $.mobile.activePage.find("div[data-role='footer']:visible");
    var content = $.mobile.activePage.find("div[data-role='content']:visible:visible");
    var viewport_height = $(window).height();

    var content_height = viewport_height - header.outerHeight() - footer.outerHeight();
    if((content.outerHeight() - header.outerHeight() - footer.outerHeight()) <= viewport_height) {
        content_height -= (content.outerHeight() - content.height());
    } 
    return content_height;
}

And here's a live jsFiddle example: http://jsfiddle.net/Gajotres/nVs9J/

这是一个实时的 jsFiddle 示例:http: //jsfiddle.net/Gajotres/nVs9J/

There's one thing to remember. This function will correctly get you maximum available content height and at the same time it can be used to stretch that same content. Unfortunately it cant be used to stretch img to full content height, img tag has an overhead of 3px.

有一件事要记住。此功能将正确获得最大可用内容高度,同时它可用于拉伸相同的内容。不幸的是,它不能用于将 img 拉伸到完整的内容高度,img 标签的开销为 3px。

Methods of markup enhancement prevention:

标记增强预防方法:

This can be done in few ways, sometimes you will need to combine them to achieve a desired result.

这可以通过几种方式完成,有时您需要将它们组合起来以达到预期的结果。

  • Method 1:

    It can do it by adding this attribute:

    data-enhance="false"
    

    to the header, content, footer container.

    This also needs to be turned in the app loading phase:

    $(document).one("mobileinit", function () {
        $.mobile.ignoreContentEnabled=true;
    });
    

    Initialize it before jquery-mobile.js is initialized (look at the example below).

    More about this can be found here:

    http://jquerymobile.com/test/docs/pages/page-scripting.html

    Example: http://jsfiddle.net/Gajotres/UZwpj/

    To recreate a page again use this:

    $('#index').live('pagebeforeshow', function (event) {
        $.mobile.ignoreContentEnabled = false;
        $(this).attr('data-enhance','true');
        $(this).trigger("pagecreate")
    });
    
  • Method 2:

    Second option is to do it manually with this line:

    data-role="none"
    

    Example: http://jsfiddle.net/Gajotres/LqDke/

  • Method 3:

    Certain HTML elements can be prevented from markup enhancement:

     $(document).bind('mobileinit',function(){
          $.mobile.page.prototype.options.keepNative = "select, input";
     });    
    

    Example: http://jsfiddle.net/Gajotres/gAGtS/

    Again initialize it before jquery-mobile.js is initialized (look at the example below).

  • 方法一:

    它可以通过添加此属性来实现:

    data-enhance="false"
    

    到页眉、内容、页脚容器。

    这也需要在应用加载阶段打开:

    $(document).one("mobileinit", function () {
        $.mobile.ignoreContentEnabled=true;
    });
    

    在 jquery-mobile.js 初始化之前对其进行初始化(看下面的例子)。

    可以在此处找到有关此内容的更多信息:

    http://jquerymobile.com/test/docs/pages/page-scripting.html

    示例:http: //jsfiddle.net/Gajotres/UZwpj/

    要再次重新创建页面,请使用以下命令:

    $('#index').live('pagebeforeshow', function (event) {
        $.mobile.ignoreContentEnabled = false;
        $(this).attr('data-enhance','true');
        $(this).trigger("pagecreate")
    });
    
  • 方法二:

    第二种选择是使用此行手动执行:

    data-role="none"
    

    示例:http: //jsfiddle.net/Gajotres/LqDke/

  • 方法三:

    可以阻止某些 HTML 元素进行标记增强:

     $(document).bind('mobileinit',function(){
          $.mobile.page.prototype.options.keepNative = "select, input";
     });    
    

    示例:http: //jsfiddle.net/Gajotres/gAGtS/

    在 jquery-mobile.js 初始化之前再次初始化它(看下面的例子)。

Markup enhancement problems:

标记增强问题:

Sometimes when creating a component from scratch (like listview) this error will occur:

有时从头开始创建组件(如 listview)时会出现此错误:

cannot call methods on listview prior to initialization

在初始化之前无法调用列表视图上的方法

It can be prevented with component initialization prior to markup enhancement, this is how you can fix this:

在标记增强之前通过组件初始化可以防止它,这是您可以解决此问题的方法:

$('#mylist').listview().listview('refresh');

Markup overrding problems:

标记覆盖问题:

If for some reason default jQuery Mobile CSS needs to be changed it must be done with !importantoverride. Without it default css styles can not be changed.

如果由于某种原因需要更改默认的 jQuery Mobile CSS,则必须使用!important覆盖来完成。没有它,默认 css 样式无法更改。

Example:

例子:

#navbar li {
    background: red !important;
}

jsFiddleexample: http://jsfiddle.net/Gajotres/vTBGa/

jsFiddle示例:http: //jsfiddle.net/Gajotres/vTBGa/

Changes:

变化:

  • 01.02.2013 - Added a dynamic navbar demo
  • 01.03.2013 - Added comment about how to dynamically add filtering to a listview
  • 07.03.2013 - Added new chapter: Get correct maximum content height
  • 17.03.2013 - Added few words to the chapter: Get correct maximum content height
  • 29.03.2013 - Added new content about dynamically created sliders and fix an example bug
  • 03.04.2013 - Added new content about dynamically created collapsible elements
  • 04.04.2013 - Added 3rd party plugins chapter
  • 20.05.2013 - Added Dynamically added Panels and contents
  • 21.05.2013 - Added another way of setting full content height
  • 20.06.2013 - Added new chapter: Markup overrding problems
  • 29.06.2013 - Added an important note of WHEN to use enhancement methods
  • 01.02.2013 - 添加了动态导航栏演示
  • 01.03.2013 - 添加了关于如何向列表视图动态添加过滤的评论
  • 07.03.2013 - 添加了新章节:获取正确的最大内容高度
  • 17.03.2013 - 在章节中添加了几句话:获取正确的最大内容高度
  • 29.03.2013 - 添加了关于动态创建的滑块的新内容并修复了一个示例错误
  • 03.04.2013 - 添加了关于动态创建的可折叠元素的新内容
  • 04.04.2013 - 添加了第 3 方插件章节
  • 20.05.2013 - 添加动态添加的面板和内容
  • 21.05.2013 - 添加了另一种设置完整内容高度的方法
  • 20.06.2013 - 添加了新章节:标记覆盖问题
  • 29.06.2013 - 添加了重要的注意事项 WHEN 以使用增强方法

回答by zzart

From JQMobile 1.4 you can do .enhanceWithin() on all the children http://api.jquerymobile.com/enhanceWithin/

从 JQMobile 1.4 开始,您可以对所有孩子执行 .enhanceWithin() http://api.jquerymobile.com/enhanceWithin/

var content = '<p>Hi</p>';
$('#somediv').html(content);
$('#somediv').enhanceWithin();