iOS保持记录我的Backbone Web应用程序

时间:2014-06-06 11:30:03

标签: javascript ios backbone.js

我希望有人能帮助我。

我有一个基于Backbone的SPA,用于响应式网站,其中.net WebAPI提供所有数据。

我最近发现了一个奇怪的问题。我添加了一个搜索框,搜索系统中的一个目录。这适用于桌面浏览器和Android。在iOS上,执行搜索似乎会将您带回到登录页面。

您可以通过各种方式执行搜索,您可以按Enter键,也可以单击搜索图标。然后,这两个触发一个方法,将路由器导航到搜索结果的URL。

我的第一个想法是,这是一些按钮怪异,但我不认为这是问题,因为两种搜索执行方法都会导致同样的问题。

搜索结果显示在受保护的视图中(它需要存在用户名 - 它存储在页面上的隐藏字段中)。网站上有两个搜索框 - 一个在主页上,另一个在搜索结果页面上(当你第一次加载它时显示一个默认设置 - 它第一次加载时很好)。两个搜索框都表现出相同的行为。

我的网站设置方式是当Backbone撤回模型时,如果它从API返回401,那么它会将您发送回登录页面,所以我只能认为它是发生在这里。

这是我的观看代码......

    function (SiansPlan, ErrorManager, RecipeSearchResult, Header, Components, TemplateSource) {
    var recipeSearchView = SiansPlan.SecureView.extend({

        name: 'Recipe Search',
        sectionName: 'Recipes',
        queryText: '',

        template: Handlebars.compile(TemplateSource),

        headerView: new Header({ text: 'Recipes', swatch: 'e' }),
        searchBoxRegion: undefined,

        $searchWrapper: undefined,
        $queryHeaderMobile: undefined,
        $queryHeaderDesktop: undefined,
        $searchButton: undefined,
        $searchInput: undefined,
        $recipeSearch : undefined,

        events: {
            'click .link-container': 'showRecipe',
            'click #searchWrapper': 'showSearch',
            'click #searchButton': 'showOrPerformSearch',
            'keydown #searchButton': 'performSearchOnEnter',
            'keydown #recipeSearch': 'performSearchOnEnter'
        },

        initialize: function (options) {
            this.options = options || {};
            SiansPlan.SecureView.prototype.initialize.call(this, options);

            this.queryText = Object.exists(this.options.query) ? this.options.query : '';
        },

        bindData: function () {
            this.$el.html(this.template({ results: this.collection.toJSON() }));
        },

        render: function () {
            var that = this;

            if (this.isSecured()) {
                this.trigger('rendering');

                var params = {
                    success: function () {
                        that.bindData();
                        that.trigger('rendered');
                    },
                    error: function (model, xhr) {
                        if (Object.exists(xhr) && xhr.status == 401) {
                            that.applyTimedOutSecureLoginPrompt();
                        } else {
                            that.$el.html('Unable to fetch search results');
                            ErrorManager.handleXhr('Search failed', xhr);
                        }
                        that.trigger('rendered');
                    }
                };

                if (!Object.exists(this.collection)) {
                    this.collection = new RecipeSearchResult.Collection({ username: SiansPlanApp.session.username(), query: this.queryText });
                }

                this.collection.fetch(params);
            } else {
                this.applySecureLoginPrompt();
            }

            return this;
        },

        postRender: function () {
            var that = this;

            var queryHeader = "All recipes";
            if (Object.hasValue(this.queryText)) {
                queryHeader = this.collection.length + " results for '" + this.queryText + "'";
            }

            this.$searchWrapper = $('#searchWrapper');
            this.$queryHeaderMobile = $('#queryHeaderMobile');
            this.$queryHeaderDesktop = $('#queryHeaderDesktop');
            this.$searchButton = $('#searchWrapper');
            this.$searchInput = $('#searchInput');
            this.$recipeSearch = $('#recipeSearch');

            this.$queryHeaderMobile.html(queryHeader);
            this.$queryHeaderDesktop.html(queryHeader);
            this.$recipeSearch.val(this.queryText);

            SiansPlanApp.session.waitForLoad(30, function () {
                that.searchBoxRegion = new SiansPlan.Region({ el: '.recipe-search-box-container' });
                that.searchBoxRegion.renderView(new Components.RecipeSearchBox({ username: SiansPlanApp.session.username(), query: that.queryText, title: 'Search' }));
            });
        },

        performSearchOnEnter: function (e) {
            if (e.keyCode == 13) {
                this.showOrPerformSearch(e);
            }
        },

        showOrPerformSearch: function (e) {
            if (!this.$searchInput.is(':visible')) {
                this.showSearch(e);
            } else {
                e.preventDefault();
                var url = '/recipes/search/' + this.$recipeSearch.val();
                window.SiansPlanApp.router.navigate(url, true);
            }
            return false;
        },

        showRecipe: function (e) {
            e.preventDefault();
            var url = $(e.target).find('a').first().attr('href');
            window.SiansPlanApp.router.navigate(url, true);
        },

        showSearch: function (e) {
            e.preventDefault();
            if (!this.$searchInput.is(':visible')) {
                this.$queryHeaderMobile.hide();
                this.$searchInput.show();
                this.$recipeSearch.focus();
                this.$recipeSearch.select();
            }
            return false;
        }
    });

    return recipeSearchView;
});

更新

我已在脚本中设置了一些警告,以查看正在进行的操作,并且我发现了以下内容......

    render: function () {
        var that = this;

        if (this.isSecured()) {
            this.trigger('rendering');

            var params = {
                success: function () {
                    alert('Bind has succeeded!');
                    that.bindData();
                    that.trigger('rendered');
                },
                error: function (model, xhr) {
                    alert('Bind has failed!');
                    if (Object.exists(xhr) && xhr.status == 401) {
                        that.applyTimedOutSecureLoginPrompt();
                    } else {
                        that.$el.html('Unable to fetch search results');
                        ErrorManager.handleXhr('Search failed', xhr);
                    }
                    that.trigger('rendered');
                    alert(xhr.status + ' ' + xhr.responseText);
                }
            };

            if (!Object.exists(this.collection)) {
                alert('Binding new collection: ' + SiansPlanApp.session.username() + ' - ' + this.queryText);
                this.collection = new RecipeSearchResult.Collection({ username: SiansPlanApp.session.username(), query: this.queryText });
            }

            alert('About to fetch using ' + this.collection.url());
            this.collection.fetch(params);
        } else {
            alert('I dont appear to be secured??');
            this.applySecureLoginPrompt();
        }

        return this;
    },
  1. 当我第一次加载页面(显示所有结果)时,它加载正常并且“成功结合!”#39;出现。 API调用是/ api / recipes / search / {username} /

  2. 当我提交搜索条件时,使用/ api / recipes / search / {username} / {query}的API调用失败(' Bind failed!')并返回401。

  3. 这让我比以前更加困惑,因为现在看起来像API问题,但其他设备工作正常,如果我向Fiddler提交相同的查询,一切都如预期的那样好。

1 个答案:

答案 0 :(得分:0)

我在最小的地方找到了答案......

问题是搜索条件有一个大写字母。因此,例如,当使用'Fish'进行搜索时,API会生成301,其重定向到/ api / recipes / search / {username} / fish。 iOS不喜欢这样,并将其报告为401(真的很糟糕!)