Git Product home page Git Product logo

baserecyclerviewadapterhelper's Issues

关于不走convert方法

你好,今天用你的适配器,不走convert方法,请问是有什么细节我没注意到吗?
public class NurseToDoAdapter extends BaseQuickAdapter<NurseTodo.ResultBean> {

public NurseToDoAdapter(Context context, NurseTodo nurseTodo) {
    super(context, R.layout.door_search_left, nurseTodo.getResult());

}

@Override
protected void convert(BaseViewHolder baseViewHolder, NurseTodo.ResultBean resultBean) {
    String time = resultBean.getStartTime() + "-" + resultBean.getEndTime();
    Log.v("09",time+"aaa");
    if (resultBean.isSelect) {
        baseViewHolder.setText(R.id.tv_search_item, time).setText(R.id.tv_search_item_name, resultBean.getServiceItem())
                .setTextColorRes(R.id.tv_search_item, R.color.white).setTextColorRes(R.id.tv_search_item_name, R.color.white)
                .setBackgroundRes(R.id.ll_search_item, R.color.colorSelect);
    }else{
        baseViewHolder.setText(R.id.tv_search_item, time).setText(R.id.tv_search_item_name, resultBean.getServiceItem())
                .setTextColorRes(R.id.tv_search_item, R.color.colorNonSelect).setTextColorRes(R.id.tv_search_item_name, R.color.colorSelect)
                .setBackgroundRes(R.id.ll_search_item, R.color.colorSearchBg);
    }
}

}

关于图片显示

感觉图片直接用glide了不太友好,如果项目中已经用了其它的图片处理方式的话,就重复了

不方便使用Data Binding功能

构造函数只支持传itemview的布局id,这样不方便使用Data Binding功能,能加上构造函数传自定义view进去的功能么

请问对数据的懒加载如何处理

举个典型的栗子,一开始要网络请求加载数据,然后在显示。

你的Adapter一开始就要指定data,虽然有add的方法,但是似乎不是很方便,而且容易报OutOfIndexException。
我看你的关于刷新加载更多的源码(PullToRefreshUseActivity),是每次重新实例个Adapter,重新设置给RecyclerView,这样做是不是高效?

请指教。

PullToRefreshUseActivity界面快速滑动很容易就挂掉了, 暂时还没发现具体原因

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{7b483c2 position=7 id=-1, oldPos=-1, pLpos:-1 no parent}
at android.support.v7.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:4499)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4630)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4611)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1988)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1384)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1347)
at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1175)
at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:1031)
at android.support.v7.widget.RecyclerView.scrollByInternal(RecyclerView.java:1504)
at android.support.v7.widget.RecyclerView.onTouchEvent(RecyclerView.java:2461)
at android.view.View.dispatchTouchEvent(View.java:8968)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2698)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2410)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2709)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2425)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2559)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1767)
at android.app.Activity.dispatchTouchEvent(Activity.java:2866)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2520)
at android.view.View.dispatchPointerEvent(View.java:9173)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4706)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4544)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4068)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4121)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4087)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4201)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4095)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4258)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4068)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4121)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4087)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4095)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4068)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6565)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6455)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6426)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6655)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
at android.view.InputEventReceiver.consumeB

第一次加入一个空数组Alist之后,第二次 AList 数据改变通知 adapter 刷新 发现无法刷新,追踪源码发现,构造函数把数据源内存地址改变了?

   public BaseQuickAdapter(Context context, int layoutResId, List<T> data) {
        this.mNextLoadEnable = false;
        this.mLoadingMoreEnable = false;
        this.mFirstOnlyEnable = true;
        this.mOpenAnimationEnable = false;
        this.mInterpolator = new LinearInterpolator();
        this.mDuration = 300;
        this.mLastPosition = -1;
        this.mSelectAnimation = new AlphaInAnimation();
        this.pageSize = -1;
        this.mData = data == null?new ArrayList():new ArrayList(data);
        this.mContext = context;
        this.mLayoutInflater = LayoutInflater.from(context);
        if(layoutResId != 0) {
            this.mLayoutResId = layoutResId;
        }

    }``

获取position

@OverRide
public void onBindViewHolder(ViewHolder holder, final int position) {

}
官方的onBindViewHolder是会返回position的,能否在你的convert方法也给回呢
@OverRide
protected void convert(BaseViewHolder baseViewHolder, Bean bean) {

}

某些情况下我只需要根据一个position去判断执行一些操作,而不是bean中的某个字段去判断

使用 setNewData()方法刷新后recyclerView变小

如题,因为有点击item刷新内容的需求,固在item的点击事件里调用了setNewData()方法,但是每刷新一次recyclerView就缩小一次
代码如下:

 mRvCate = (RecyclerView) viewHeaderAds.findViewById(R.id.rv_mall_coin_cate_list);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        mRvCate.setLayoutManager(linearLayoutManager);
        final BaseQuickAdapter<CateEntity.DataBean.ListBean> mAdapterCate = new BaseQuickAdapter<CateEntity.DataBean.ListBean>(this,
                R.layout.item_mall_coin_cate, mCoinCateData.getList()) {
            @Override
            protected void convert(BaseViewHolder baseViewHolder, CateEntity.DataBean.ListBean listBean) {
                AutoUtils.autoSize(baseViewHolder.getConvertView());
                if (mCoinCateSelected == baseViewHolder.getAdapterPosition()) {
                    baseViewHolder.setBackgroundRes(R.id.arl_mall_coin_cate, R.drawable.mall_coin_selected);
                    baseViewHolder.setTextColor(R.id.tv_mall_coin_cate, getResources().getColor(R.color.color_white_fffeff));
                }
                baseViewHolder.setImageUrl(R.id.iv_mall_coin_cate, listBean.getPic());
                baseViewHolder.setText(R.id.tv_mall_coin_cate, listBean.getName());
            }
        };
        mAdapterCate.setOnRecyclerViewItemClickListener(new BaseQuickAdapter.OnRecyclerViewItemClickListener() {
            @Override
            public void onItemClick(View view, int i) {
//                AutoRelativeLayout viewById = (AutoRelativeLayout) view.findViewById(R.id.arl_mall_coin_cate);
//                viewById.setBackgroundResource(R.drawable.mall_coin_selected);
//                TextView tv = (TextView) view.findViewById(R.id.tv_mall_coin_cate);
//                tv.setTextColor(getResources().getColor(R.color.color_white_ffffff));
                mCoinCateSelected = i;
                mAdapterCate.setNewData(mCoinCateData.getList());
                downProductList(mCoinCateData.getList().get(mCoinCateSelected).getId());
            }
        });
        mRvCate.setAdapter(mAdapterCate);

添加头部后,头部只占了一半的宽度

需求是一个2栏的GridView,但是添加了头部后头部也被压缩到了item的宽度,代码如下

mGvMallEcohList.setLayoutManager(new GridLayoutManager(this, 2));
        mAdapterEcohProduct.addHeaderView(viewHeader);
        mGvMallEcohList.setAdapter(mAdapterEcohProduct);

PullToRefreshUseActivity上拉刷新

mQuickAdapter.openLoadMore(PAGE_SIZE, false) 设置为false,使其不能进行上拉加载,然而进行下拉刷新后,上拉加载就可以加载了,这是怎么回事?

图片加载可以优化,做成扩展

如果项目已经集成了其他图片加载框架,但是你这个项目又集成了Glide图片加载库,这样项目就存在了两个图片加载框架,然而这不是我们想要达到的效果。期待作者可以优化这块~

GridLayoutManager header和Load more的问题

当使用GridLayoutManager的时候,addHeaderView占的spansize应该是整个宽度,可以通过一下设置解决问题
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@OverRide
public int getSpanSize(int position) {
if (position == 0) {
return 2;
}
return 1;
}
});
但是loadmore view占地spansize不是整个宽度,看了下代码,loadmore处理了StaggeredGridLayoutManager的情况,但是StaggeredGridLayoutManager的时候addHeaderView的spansize不知道如何处理

当用StaggeredGridLayoutManager时用使用emptyview时不能占整行

setEmptyView 没有考虑StaggeredGridLayoutManager或者GridLayoutManager的情况可以考虑在重写onViewAttachedToWindow

`

    if (holder.getItemViewType() == EMPTY_VIEW) {
        if (holder.itemView.getLayoutParams() instanceof StaggeredGridLayoutManager.LayoutParams) {
            StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams();
            params.setFullSpan(true);
        }
    }

`

替换emptyview

作者你好,我又来提一波意见了。源码里面你只给出了setEmptyView的方法,你的本意可能只是在空数据的时候给用户一个友好的界面提示,但是网络错误以及正在加载的view我也想直接用你的setEmptyView(),发现有一种情况,就是当发送网络请求我传了一个正在加载的页面进去,请求成功发现没数据,我想替换emptyView,这时候直接setEmptyView是没效果的,最后发现得再重新set一次adpter才有效果,这样虽然能替换emptyView,但感觉这样用总不太好。所以在想,是否能对emptyView定义更广一些,不仅仅是emptyView,而是能传任何我想要的view。

IndexOutOfBoundsException

Process: com.chad.baserecyclerviewadapterhelper, PID: 3219
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{110301db position=13 id=-1, oldPos=-1, pLpos:-1 no parent}
at android.support.v7.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:4505)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4636)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4617)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:1994)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1390)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1353)
at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1180)
at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:1031)
at android.support.v7.widget.RecyclerView.scrollByInternal(RecyclerView.java:1529)
at android.support.v7.widget.RecyclerView.onGenericMotionEvent(RecyclerView.java:2578)
at android.view.View.dispatchGenericMotionEventInternal(View.java:8493)
at android.view.View.dispatchGenericMotionEvent(View.java:8474)
at android.view.ViewGroup.dispatchTransformedGenericPointerEvent(ViewGroup.java:2024)
at android.view.ViewGroup.dispatchGenericPointerEvent(ViewGroup.java:1975)
at android.view.View.dispatchGenericMotionEvent(View.java:8467)
at android.view.ViewGroup.dispatchTransformedGenericPointerEvent(ViewGroup.java:2024)
at android.view.ViewGroup.dispatchGenericPointerEvent(ViewGroup.java:1975)
at android.view.View.dispatchGenericMotionEvent(View.java:8467)
at android.view.ViewGroup.dispatchTransformedGenericPointerEvent(ViewGroup.java:2024)
at android.view.ViewGroup.dispatchGenericPointerEvent(ViewGroup.java:1975)
at android.view.View.dispatchGenericMotionEvent(View.java:8467)
at android.view.ViewGroup.dispatchTransformedGenericPointerEvent(ViewGroup.java:2024)
at android.view.ViewGroup.dispatchGenericPointerEvent(ViewGroup.java:1975)
at android.view.View.dispatchGenericMotionEvent(View.java:8467)
at android.view.ViewGroup.dispatchTransformedGenericPointerEvent(ViewGroup.java:2024)
at android.view.ViewGroup.dispatchGenericPointerEvent(ViewGroup.java:1975)
at android.view.View.dispatchGenericMotionEvent(View.java:8467)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchGenericMotionEvent(PhoneWindow.java:2322)
at com.android.internal.policy.impl.PhoneWindow.superDispatchGenericMotionEvent(PhoneWindow.java:1702)
at android.app.Activity.dispatchGenericMotionEvent(Activity.java:2775)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchGenericMotionEvent(PhoneWindow.java:2289)
at android.view.View.dispatchPointerEvent(View.java:8580)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4021)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3887)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3502)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3578)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3476)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3635)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3502)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3476)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5701)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRo

onLoadMoreRequested只执行一次

当我加载了一页或者几页数据后,这时候把网断了,滑到底部执行onLoadMoreRequested(),没有加载到数据,之后我再把网连上,我再滑到底部就不会执行onLoadMoreRequested()方法了

获取某个item的view

使用过程中遇到这样的需求,点击某个item改变它的背景颜色,类似选中效果,再点击另外一个item,之前选中的item要变回原来的颜色,所以想要根据item的position拿到它的view,希望作者能加多这个方法,感激不尽。

BaseQuickAdapter中的setTag有什么意义

@OverRide
public void onBindViewHolder(BaseAdapterHelper helper, int position) {
helper.itemView.setTag(position);
T item = getItem(position);
convert((H) helper, item);
}
代码如上

我看貌似没有地方用到这个tag啊

多类型item的适配器时

目前BaseRecyclerViewAdapterHelpter在满足多类型的item时,需要使用方在写Bean时继承MultiItemEntity,
但是一般情况下使用方的Bean会继承他们自己的BaseBean,所以这样会导致别人要改,
我的建议是框架提供通用的item布局类型,eg:HEADER_VIEW;EMPTY_VIEW;LOADING_VIEW;FOOTER_VIEW;
剩下的item布局类型交给使用方的具体子类去依照他自己的Bean去区分提供,也即int getDefItemViewType(int position) {},但由于目前abstract class BaseMultiItemQuickAdapter 中T 限制需要继承MultiItemEntity,所以对使用方有所限制,可以把 MultiltemEntity提升为接口,这样使用方自己的Bean仍然可以继承他们自己的BaseBean,并且实现MultiItemEntity提升后的接口就行了。

加载更多的问题

加载更多时,假如是grid布局怎么办,现在是线性的,加载更多没问题

Manifest merger failed : Attribute application@allowBackup conflict

This error occured when compile。

Error:Execution failed for task ':app:processDebugManifest'.
> Manifest merger failed : Attribute application@allowBackup value=(false) from AndroidManifest.xml:20:9-36
    is also present at [com.github.CymChad:BaseRecyclerViewAdapterHelper:v1.7.4] AndroidManifest.xml:12:9-35 value=(true).
    Suggestion: add 'tools:replace="android:allowBackup"' to <application> element at AndroidManifest.xml:18:5-235:19 to override.

I suggest you set android:allowBackup="false" to ensure security。

在item里面再放一个recycleview时出现了巨大的问题

我想在 recycleview 的 item 里面再放一个 recycleview
但是在 holder.setAdapter(R.id.rv_dragNames,adapter); 的时候
他需要的是 android.widget.Adapter
而recycleview的是 android.support.v7.widget.RecyclerView;
希望帅气又有才华的作者解决一下这个问题

能否考虑一下加入RecyclerView的SwipeMenu操作?

是从微博(伯乐在线的官博)上看到的,也是刚刚试用了一下,仅仅是看demo就感觉满足日常所需,但是我当前在重构之前的项目,由于之前使用的ListView使用了SwipeMenu,在重构过程中全部将ListView替换成RecyclerView,其它的感觉还比较好解决,使用了您的代码后确实是将Adapter代码量减少了很多,高度封装且接口使用简单,这个是我很短时间内的使用感受。只是有一个问题,如何将SwipeMenu集成进来,不想分开做,感觉很冗余,水平有限,特此求助。
另:附上实现SwipeMenu地址:http://www.open-open.com/lib/view/open1453175513105.html。
再次感谢,源码尚未全部阅读,已然受益匪浅。
以上。

1.6.8有个app_name字符串资源的冲突问题

看截图
image

在编译后生成的代码里有个 values-en 目录,里面的 values-en.xml 有个 app_name = Library
结果就是这个 app_name 把我原本的 app_name 给覆盖了,原因应该是他显式的指定了英语的values资源,优先级高于默认的英语资源(没有指定语言的资源)?

所以我 app 的名字就变成了 Library 。。。哭死。。。

我之前用的 1.6.1,没有这个问题,确认没有这个 values-en 目录,切回 1.6.8 就有了。
我没有去试 1.6.1 - 1.6.8 之间的版本。

运行异常

在Android studio中创建了一个新的项目,然后按照操作步骤创建adapter,运行时异常
:app:preBuild UP-TO-DATE
:app:preDebugBuild UP-TO-DATE
:app:checkDebugManifest
:app:preReleaseBuild UP-TO-DATE
:app:prepareComAndroidSupportAnimatedVectorDrawable2340Library UP-TO-DATE
:app:prepareComAndroidSupportAppcompatV72340Library UP-TO-DATE
:app:prepareComAndroidSupportRecyclerviewV72330Library UP-TO-DATE
:app:prepareComAndroidSupportSupportV42340Library UP-TO-DATE
:app:prepareComAndroidSupportSupportVectorDrawable2340Library UP-TO-DATE
:app:prepareComGithubCymChadBaseRecyclerViewAdapterHelperV178Library UP-TO-DATE
:app:prepareDebugDependencies
:app:compileDebugAidl UP-TO-DATE
:app:compileDebugRenderscript UP-TO-DATE
:app:generateDebugBuildConfig UP-TO-DATE
:app:generateDebugAssets UP-TO-DATE
:app:mergeDebugAssets UP-TO-DATE
:app:generateDebugResValues UP-TO-DATE
:app:generateDebugResources UP-TO-DATE
:app:mergeDebugResources
AAPT err(Facade for 758995742): libpng error: Not a PNG file
Error:Execution failed for task ':app:mergeDebugResources'.

Some file crunching failed, see logs for details

请问这是怎么回事?
另外我把github上down下的项目,按照上述操作,运行也是异常

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.