Backbone:删除省略号onclick

问题描述 投票:2回答:1

一点背景

我正在尝试创建一个类似于Twitter的推文,其中推文/行将展开,显示更多信息。

数据从JSON文件(从后端发送到前端)中提取。我使用骨干来渲染前端的数据。

假设我的Feed显示10行,每行显示一些信息,然后点击row / div展开以显示更多信息。描述字段包含大量文本,因此我在其上应用JavaScript省略号。我使用Javascript省略号,因为简短描述需要多行(不要认为CSS省略号适用于多行)。

  1. 我创建了一个插件,它将截断描述文本并onclick我想删除省略号并将其替换为完整描述(因为行将展开)。
  2. 我创建了一个插件,可以将完整的描述(在被截断之前)保存到数组中。

问题

我的想法是将单击的行的索引(currentTarget)与保存的行的索引(在数组中)进行比较,然后用完整描述替换省略号文本,然后使用jQuery animate展开div。

我不确定是否有办法从主干“点击事件”中获取索引(为了将其与保存在数组中的索引进行比较)?

如果有更好的方法来解决这个问题,请随时告诉我。

提前致谢

这是我的代码:

截断并保存原始文本功能

/**
 * Plugins
 */
var arr = [];

$.fn.truncate = function(){
    return this.each(function(index,element){
        var elementText = $(element).text();
        if(elementText.length > 165){
            var truncated = elementText.trim().substring(0, 165).split(" ").slice(0, -1).join(" ") + "…";
        }
        $(element).text(truncated);
    });
};

$.fn.getText = function(){
    return this.each(function(index,element){
        arr.push({
            i: index,
            v: $(element).text()
        });
    });
};

骨干模型和集合

/**
 * Model
 */
var Task = Backbone.Model.extend();

/**
 * Collections
 */
var RecentTasksList = Backbone.Collection.extend({
    model: Task,
    url: 'json/recentTasks.json'
});

骨干视图

/**
 * Views
 */
var RecentTasksView = Backbone.View.extend({
    el: '.taskList',
    template: _.template($('#recentTasksTemplate').html()),
    render: function(){
        _.each(this.model.models, function(data){
            this.$el.append(this.template(data.toJSON()));
        }, this);

        $('.description').getText();
        $('.description').truncate();

        return this;
    }
});

var FullTaskView = Backbone.View.extend({
    el: '.taskContainer',
    events: {
        'click .task': 'showFullDetails'
    },
    showFullDetails: function(e){
        var eTarget = $(e.currentTarget);
        var $desc = $('.description');

        if(eTarget.hasClass('expanded')){
            eTarget.animate({
                'height': '80px'
            },
            function(){
                eTarget.removeClass('expanded');
            });
        }
        else{
            console.log($(eTarget).find($desc).html());

            eTarget.animate({
                //doesn't work lesser IE 8
                'height': eTarget[0].scrollHeight
            },
            function(){
                eTarget.addClass('expanded');
            });     
        }
    }
});

var AppView = Backbone.View.extend({
    el: 'body',
    initialize: function(){
        //Recent Tasks
        var recentTasksList = new RecentTasksList();
        var recentTasksView = new RecentTasksView({
            model: recentTasksList
        });
        recentTasksList.bind('reset', function(){
            recentTasksView.render();
        });
        recentTasksList.fetch();

        //Full Task Details
        var fullTaskView = new FullTaskView();
    }
});

var appView = new AppView();

下划线模板

<script id="recentTasksTemplate" type="text/template">
    <div class="task clearfix">
        <div class="image">
            <img src="<%= image %>" />
        </div>
        <div class="details">
            <h3 class="title"><%= title %></h3>
            <div class="description">
                <%= description %>
            </div>
        </div>
    <div>
</script>

HTML

<div class="taskContainer">
    <div class="taskList"></div>
</div>

编辑

最后一个问题。我在页面中添加了一个标签(类似的号召性用语)。将显示相同类型的信息(我使用相同的模板)。例如,我现在有RecentTask和PopularTask。我为包含点击事件的标签创建了一个视图。我是否需要每次都实例化模型并查看和获取数据,还是可以重用已经初始化的数据?

我为第二个标签创建了一个新视图。从服务器抓取JSON文件:

var PopularTasksList = Backbone.Collection.extend({
    model: Task,
    url: 'json/popularTasks.json'
});

var PopularTasksView = Backbone.View.extend({
    el: '.taskList',
    render: function(){
        $('.taskList').empty();
        _.each(this.model.models, function(model){
            var taskView = new TaskView({model: model});
            this.$el.append(taskView.render().el);
        }, this);
        return this;
    }
});

然后我创建了一个选项卡视图,它将显示正确的任务onclick。

var TabsView = Backbone.View.extend({
            el: 'body',
            events:{
                'click .tabRecent': 'fetchDataRecentTasks',
                'click .tabPopular': 'fetchDataPopularTasks'
            },
            fetchDataRecentTasks: function(){
                var recentTasksList = new RecentTasksList();
                var recentTasksView = new RecentTasksView({
                    model: recentTasksList
                });
                recentTasksList.bind('reset', function(){
                    recentTasksView.render();
                });
                recentTasksList.fetch();
            },
            fetchDataPopularTasks: function(){
                var popularTasksList = new PopularTasksList();
                var popularTasksView = new PopularTasksView({
                    model: popularTasksList
                });     
                popularTasksList.bind('reset', function(){
                    popularTasksView.render();
                });
                popularTasksList.fetch();
            }
        });
javascript jquery backbone.js underscore.js ellipsis
1个回答
2
投票

我认为您应该为单个任务创建一个新视图。然后在该视图中,您可以处理单击,以便您可以访问任务模型,并且还可以非常轻松地访问该视图的DOM。

然后你可以摆脱你的FullTask​​View和jQuery插件。

 /**
 * Model
 */
var Task = Backbone.Model.extend({
    getShortDescription: function(){
       var desc = this.get('description');
       if(desc.length > 165){
        return desc.trim().substring(0, 165).split(" ").slice(0, -1).join(" ") + "…";
       }
       return desc;
    }
});

添加新的TaskView,并更改RecentTasksView以创建/渲染它们。

/**
 * Views
 */

var TaskView = Backbone.View.extend({
    template: _.template($('#recentTasksTemplate').html()),
    events: {
       'click': 'showFullDetails'
    },
    render: function(){
        // pass the model json, plus the short description to the template
        this.$el.html(this.template({
            data: this.model.toJSON(), 
            shortDesc: this.model.getShortDescription()
            }));

        return this;
    },
    showFullDetails: function(){
       // change text, show/hide, animate here
       // In the view, this.$() will only match elements within this view.

       // if expand...
       this.$('.description').html(this.model.get('description'));

       // if hide...
       this.$('.description').html(this.model.getShortDescription());
    }
});
var RecentTasksView = Backbone.View.extend({
    el: '.taskList',
    render: function(){
        _.each(this.model.models, function(model){
            // create a view for each task, render and append it
            var taskView = new TaskView({model: model});
            this.$el.append(taskView.render().el);
        }, this);

        return this;
    }
});

更改模板以使用传递给它的新数据。

// access the model stuff with data.title, etc. 
<script id="recentTasksTemplate" type="text/template">
    <div class="task clearfix">
        <div class="image">
            <img src="<%= data.image %>" />
        </div>
        <div class="details">
            <h3 class="title"><%= data.title %></h3>
            <div class="description">
                <%= shortDesc %>
            </div>
        </div>
    <div>
</script>

编辑:

Backbone视图用于管理DOM元素,因此将每个任务作为自己的视图实例是个好主意。这样可以更轻松地根据点击进行扩展和更改文本。此外,最佳做法是不在视图外部更改DOM元素内的代码,因此最好在每个任务视图中执行该操作。

这类似于Todo示例中的TodoView:

http://backbonejs.org/docs/todos.html

http://backbonejs.org/examples/todos/index.html

您可以将模板函数传递给任何javascript对象(甚至是具有函数的对象,而不仅仅是属性)。由于您希望显示一些技术上不属于模型的数据,因此传递data对象只是将所需内容添加到模板中的一种方法。

© www.soinside.com 2019 - 2024. All rights reserved.