For terrain glDrawElements is the way to go, assuming you have a simple 2d grid, and you displace it on the vertex shader or send heights as vertex attribs. It's much faster than glDrawArrays for this kind of mesh.
For the textures: I don't know if you want to texture the terrain with one big texture, or more textures blended together, for example a simple grass pattern, or grass blended to snow with increasing height.
The first one is pretty easy: lets say your terrain's width is W and its height is H. You use one big texture over the whole map. Then the texture coord for one vertex is:
vec2 TexCoord = vec2(VertexPos.x/W,VertexPos.z/H);
For the second it changes a bit:
If your texture is a simple grass tile, or anything that you want to cover the whole terrain with, then texture coord of a vertex is:
vec2 TexCoord = vec2(VertexPos.x/XdirectionTileSize,VertexPos.z/ZdirectionTileSize);
XdirectionTileSize and ZdirectionTileSize are the dimensions of one pattern. For example you want to fetch a grass texture over the terrain with 1 meters * 1 meters resolution, and your vertices are each 2 meters away from each other, then set them to 0.5 (1/2).
For more textures you can define more tile-sizes, and one big texture map with each color defining one material. Example: red is grass, blue is snow, green is sand, and alpha is rock. Then you blend the textures like this: (You can fetch this big material map just like the one big texture)
color = materialmap.r*grass + materialmap.b*snow + materialmap.g*sand + materialmap.a*rock;
And finally my favorite method for terrain texturing is procedural shader splatting. I won't write it here. For example the Frostbite Engine (Battlefields) uses this. Here's a link to a very good presentation: Terrain Rendering in Frostbite Using Procedural Shader Splatting. In short it's like masking. Rendering the heights, normals, slopes into an FBO texture, and using it like in deferred rendering/shading.
For quality: if your texcoords are calculated in a shader with vertex positions on a plane (.xy, .xz), it can distort textures with increasing slope. The solution for this problem is triplanar texturing. Bottom of the page: Generating Complex Procedural Terrains Using the GPU. In short: it projects the texture to the terrain from 3 planes (xz, xy, yz) and mixes/blends them with normals.
Of course you can mix these texturing methods. I know it doesn't directly answer your question, but I don't think you should pass texture coordinates as vertex attribs. It's much easier defining them with big textures, tiles, or splatting. Oh, and I hope you use shaders;).