问:
jQuery + Bootstrap Navigation Bar - How to highlight the link when visited
Please visit this link.

Try to click "Portfolio" link, it should be highlighted with blue background.

But after clicking outside the navigation bar it will be highlighted with blue.

```<code>    //scrolling
$('nav a').on('click', function() {

    var scrollAnchor = $(this).attr('data-scroll'),
        scrollPoint = $('section[data-anchor="' + scrollAnchor + '"]').offset().top;

    $('body,html').animate({
        scrollTop: scrollPoint
    }, 500);

    return false;

});

//change color
$(window).scroll(function() {
    var windscroll = $(window).scrollTop();
    if (windscroll) {
        $('section').each(function(i) {
            if ($(this).position().top <= windscroll) {
                $('nav a.active').removeClass('active');
                $('nav a').eq(i).addClass('active');
            }
        });

    }
}).scroll();
</code>```

答:
Just like hover there is also visited,where you can assign color for the visted links.</p>

```<code>a:visited {
    color: blue;
}
</code>```

Body:
Please visit this link.

Try to click "Portfolio" link, it should be highlighted with blue background.

But after clicking outside the navigation bar it will be highlighted with blue.

    //scrolling
$('nav a').on('click', function() {

    var scrollAnchor = $(this).attr('data-scroll'),
        scrollPoint = $('section[data-anchor="' + scrollAnchor + '"]').offset().top;

    $('body,html').animate({
        scrollTop: scrollPoint
    }, 500);

    return false;

});

//change color
$(window).scroll(function() {
    var windscroll = $(window).scrollTop();
    if (windscroll) {
        $('section').each(function(i) {
            if ($(this).position().top <= windscroll) {
                $('nav a.active').removeClass('active');
                $('nav a').eq(i).addClass('active');
            }
        });

    }
}).scroll();

Body:
Just like hover there is also visited,where you can assign color for the visted links.

a:visited {
    color: blue;
}


来源: stackexchange

问:
How to modify algorithm to return a triangle with different colors of vertices
I have fragment and vertex, and I am not able to call in the java code, to compile a triangle, with each vertex defining a color.

```<code>package Projeto_2;

import com.jogamp.opengl.*;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.util.Animator;

import java.io.BufferedReader;
import java.io.FileReader;

/**
* JSingleTriangle.java <BR>
*
*
* Java implementation of example (listing 2.8 and 2.9) of the OpenGL  SuperBible 6th Edition.
 * Not exactly the same but an adaptation.
*/

public final class Projeto_2 implements GLEventListener {

private GL4 gl;

private static int width=600;
private static int height=600;

private int shaderProgram;
private int vertShader;
private int fragShader;

private int[] vao;

public static void main(String[] s) {

    // This demo is based on the GL4 GLProfile
    GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL4));

    // The demo uses the NEWT (Native Windowing Toolkit) Programming Library
    GLWindow glWindow = GLWindow.create(caps);

    // Setup the GLWindow
    glWindow.setTitle("Single Triangle - JOGL");
    glWindow.setSize(width,height);
    glWindow.setUndecorated(false);
    glWindow.setPointerVisible(true);
    glWindow.setVisible(true);

    // Finally we connect the GLEventListener application code to the GLWindow.
    // GLWindow will call the GLEventListener init, reshape, display and dispose functions when needed.
    glWindow.addGLEventListener(new Projeto_2());
    Animator animator = new Animator();
    animator.add(glWindow);
    animator.start();
}

public void init(GLAutoDrawable drawable) {
    System.out.println("init");

    gl = drawable.getGL().getGL4();

    // Create GPU shader handles
    vertShader = loadShader(GL4.GL_VERTEX_SHADER, "./src/shader.vert");
    fragShader = loadShader(GL4.GL_FRAGMENT_SHADER, "./src/shader.frag");
    //Each shaderProgram must have one vertex shader and one fragment shader.
    shaderProgram = gl.glCreateProgram();
    gl.glAttachShader(shaderProgram, vertShader);
    gl.glAttachShader(shaderProgram, fragShader);

    //gl.glBindAttribLocation(shaderProgram, 0, "attribute_Position"); /////////////////////////////
   // gl.glBindAttribLocation(shaderProgram, 1, "attribute_Color"); ////////////////////////////

    gl.glLinkProgram(shaderProgram);
    // Check link status.
    int[] linked = new int[1];
    gl.glGetProgramiv(shaderProgram, GL4.GL_LINK_STATUS, linked, 0);
    if(linked[0]!=0){System.out.println("Shaders succesfully linked");}
    else {
        int[] logLength = new int[1];
        gl.glGetProgramiv(shaderProgram, GL4.GL_INFO_LOG_LENGTH, logLength, 0);

        byte[] log = new byte[logLength[0]];
        gl.glGetProgramInfoLog(shaderProgram, logLength[0], (int[])null, 0, log, 0);

        System.err.println("Error linking shaders: " + new String(log));
        System.exit(1);
    }

    gl.glUseProgram(shaderProgram);

    vao = new int[1];
    gl.glGenVertexArrays(1, vao, 0);
    gl.glBindVertexArray(vao[0]);

};

public void reshape(GLAutoDrawable drawable, int x, int y, int z, int h) {
    System.out.println("reshape - Window resized to width=" + z + " height=" + h);
    width = z;
    height = h;

    // Optional: Set viewport
    // Render to a square at the center of the window.
    gl.glViewport((width-height)/2, 0, height, height);
}

public void display(GLAutoDrawable drawable) {
    float[] bg = {0.0f, 0.0f, 0.0f, 1.0f};
    gl.glClearBufferfv(GL4.GL_COLOR, 0, bg, 0);

    gl.glDrawArrays(GL4.GL_TRIANGLES, 0, 3);
}

public void dispose(GLAutoDrawable drawable) {
    System.out.println("Dispose");
    System.out.println("cleanup, remember to release shaders");
    gl.glUseProgram(0);
    gl.glDetachShader(shaderProgram, vertShader);
    gl.glDeleteShader(vertShader);
    gl.glDetachShader(shaderProgram, fragShader);
    gl.glDeleteShader(fragShader);
    gl.glDeleteProgram(shaderProgram);
    System.exit(0);
    System.exit(0);
}

public int loadShader(int type, String filename ) {
    int shader;

    // Create GPU shader handle
    shader = gl.glCreateShader(type);

    // Read shader file
    String[] vlines = new String[1];
    vlines[0] = "";
    String line;

    try{
        BufferedReader reader = new BufferedReader(new FileReader(filename));
        while((line = reader.readLine()) != null) {
            vlines[0] += line + "\n";  // insert a newline character after each line
        }
        reader.close();
    } catch (Exception e) {
        System.err.println("Fail reading shader file");
    }

    gl.glShaderSource(shader, vlines.length, vlines, null);

    // Compile shader
    gl.glCompileShader(shader);

    // Check compile status.
    int[] compiled = new int[1];
    gl.glGetShaderiv(shader, GL4.GL_COMPILE_STATUS, compiled, 0);
    if(compiled[0]!=0){System.out.println("Shader succesfully compiled");}
    else {
        int[] logLength = new int[1];
        gl.glGetShaderiv(shader, GL4.GL_INFO_LOG_LENGTH, logLength, 0);

        byte[] log = new byte[logLength[0]];
        gl.glGetShaderInfoLog(shader, logLength[0], (int[])null, 0, log, 0);

        System.err.println("Error compiling the shader: " + new String(log));
        System.exit(1);
    }

    return shader;
}
</code>```

I do not know what function to call the two shaders, to generate this triangle with three vertices and each vertex defining the colors red, blue and green.

Shader.frag

```<code> #version 400 core

 in vec4 varying_Color; // incoming varying data to the
                   // fragment shader
                   // sent from the vertex shader

 void main (void) {
 gl_FragColor = varying_Color;
 }
</code>```

shader.vert

```<code>#version 400 core

in vec4 attribute_Position; // vertex shader
in vec4 attribute_Color; // attributes

out vec4 varying_Color; // Outgoing varying data
                    // sent to the fragment shader
void main (void) {
varying_Color = attribute_Color;
gl_Position = attribute_Position;
}
</code>```

答:
I do not use JAVA nor JOGL either so I may be wrong but my OpenGL experience is telling me that your vertex shader does not look OK to me especially this:

```<code>#version 400 core
in vec4 attribute_Position; // vertex shader
in vec4 attribute_Color; // attributes
</code>```

You chose GL 4.00 core profile and using in as an input. That would work if your input was provided from shader above vertex but I think that is not the case (as you got only vertex and fragment) so you should have something like this instead:

```<code>#version 400 core
layout(location=0) in vec4 attribute_Position;
layout(location=1) in vec4 attribute_Color;
</code>```

Also you should bind position and color VBO to these locations so unrem your

```<code>gl.glBindAttribLocation(shaderProgram, 0, "attribute_Position");
gl.glBindAttribLocation(shaderProgram, 1, "attribute_Color");
</code>```

bindings in the code but I am not familiar with that I am more used to this:

```<code>// bind VBO
glBindBuffer(vbotype,vboid);
glEnableVertexAttribArray(vbolocation);
glVertexAttribPointer(vbolocation,datacomponents,datatype,GL_FALSE,0,0);

// unbind VBO
glBindBuffer(vbotype,0);
glDisableVertexAttribArray(vbolocation);
</code>```

Where each VBO has these:

```<code>GLuint vboid;                       // OpenGL id for current VBO
int    vbolocation;                 // intended VBO atrib layout location for GLSL
GLuint vbotype;                     // GL_ARRAY_BUFFER,GL_ELEMENT_ARRAY_BUFFER
GLuint datatype;                    // GL_FLOAT,GL_UNSIGNED_INT
GLuint datacomponents;              // vector size 1,2,3,4
List<GLint> data;                   // 32bit vbo data (always overtype with datatype on any access!!!)
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I have fragment and vertex, and I am not able to call in the java code, to compile a triangle, with each vertex defining a color.

package Projeto_2;

import com.jogamp.opengl.*;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.util.Animator;

import java.io.BufferedReader;
import java.io.FileReader;

/**
* JSingleTriangle.java

*
*
* Java implementation of example (listing 2.8 and 2.9) of the OpenGL  SuperBible 6th Edition.
 * Not exactly the same but an adaptation.
*/

public final class Projeto_2 implements GLEventListener {

private GL4 gl;

private static int width=600;
private static int height=600;

private int shaderProgram;
private int vertShader;
private int fragShader;

private int[] vao;

public static void main(String[] s) {

    // This demo is based on the GL4 GLProfile
    GLCapabilities caps = new GLCapabilities(GLProfile.get(GLProfile.GL4));

    // The demo uses the NEWT (Native Windowing Toolkit) Programming Library
    GLWindow glWindow = GLWindow.create(caps);

    // Setup the GLWindow
    glWindow.setTitle("Single Triangle - JOGL");
    glWindow.setSize(width,height);
    glWindow.setUndecorated(false);
    glWindow.setPointerVisible(true);
    glWindow.setVisible(true);

    // Finally we connect the GLEventListener application code to the GLWindow.
    // GLWindow will call the GLEventListener init, reshape, display and dispose functions when needed.
    glWindow.addGLEventListener(new Projeto_2());
    Animator animator = new Animator();
    animator.add(glWindow);
    animator.start();
}

public void init(GLAutoDrawable drawable) {
    System.out.println("init");

    gl = drawable.getGL().getGL4();

    // Create GPU shader handles
    vertShader = loadShader(GL4.GL_VERTEX_SHADER, "./src/shader.vert");
    fragShader = loadShader(GL4.GL_FRAGMENT_SHADER, "./src/shader.frag");
    //Each shaderProgram must have one vertex shader and one fragment shader.
    shaderProgram = gl.glCreateProgram();
    gl.glAttachShader(shaderProgram, vertShader);
    gl.glAttachShader(shaderProgram, fragShader);

    //gl.glBindAttribLocation(shaderProgram, 0, "attribute_Position"); /////////////////////////////
   // gl.glBindAttribLocation(shaderProgram, 1, "attribute_Color"); ////////////////////////////

    gl.glLinkProgram(shaderProgram);
    // Check link status.
    int[] linked = new int[1];
    gl.glGetProgramiv(shaderProgram, GL4.GL_LINK_STATUS, linked, 0);
    if(linked[0]!=0){System.out.println("Shaders succesfully linked");}
    else {
        int[] logLength = new int[1];
        gl.glGetProgramiv(shaderProgram, GL4.GL_INFO_LOG_LENGTH, logLength, 0);

        byte[] log = new byte[logLength[0]];
        gl.glGetProgramInfoLog(shaderProgram, logLength[0], (int[])null, 0, log, 0);

        System.err.println("Error linking shaders: " + new String(log));
        System.exit(1);
    }

    gl.glUseProgram(shaderProgram);

    vao = new int[1];
    gl.glGenVertexArrays(1, vao, 0);
    gl.glBindVertexArray(vao[0]);

};

public void reshape(GLAutoDrawable drawable, int x, int y, int z, int h) {
    System.out.println("reshape - Window resized to width=" + z + " height=" + h);
    width = z;
    height = h;

    // Optional: Set viewport
    // Render to a square at the center of the window.
    gl.glViewport((width-height)/2, 0, height, height);
}

public void display(GLAutoDrawable drawable) {
    float[] bg = {0.0f, 0.0f, 0.0f, 1.0f};
    gl.glClearBufferfv(GL4.GL_COLOR, 0, bg, 0);

    gl.glDrawArrays(GL4.GL_TRIANGLES, 0, 3);
}

public void dispose(GLAutoDrawable drawable) {
    System.out.println("Dispose");
    System.out.println("cleanup, remember to release shaders");
    gl.glUseProgram(0);
    gl.glDetachShader(shaderProgram, vertShader);
    gl.glDeleteShader(vertShader);
    gl.glDetachShader(shaderProgram, fragShader);
    gl.glDeleteShader(fragShader);
    gl.glDeleteProgram(shaderProgram);
    System.exit(0);
    System.exit(0);
}

public int loadShader(int type, String filename ) {
    int shader;

    // Create GPU shader handle
    shader = gl.glCreateShader(type);

    // Read shader file
    String[] vlines = new String[1];
    vlines[0] = "";
    String line;

    try{
        BufferedReader reader = new BufferedReader(new FileReader(filename));
        while((line = reader.readLine()) != null) {
            vlines[0] += line + "\n";  // insert a newline character after each line
        }
        reader.close();
    } catch (Exception e) {
        System.err.println("Fail reading shader file");
    }

    gl.glShaderSource(shader, vlines.length, vlines, null);

    // Compile shader
    gl.glCompileShader(shader);

    // Check compile status.
    int[] compiled = new int[1];
    gl.glGetShaderiv(shader, GL4.GL_COMPILE_STATUS, compiled, 0);
    if(compiled[0]!=0){System.out.println("Shader succesfully compiled");}
    else {
        int[] logLength = new int[1];
        gl.glGetShaderiv(shader, GL4.GL_INFO_LOG_LENGTH, logLength, 0);

        byte[] log = new byte[logLength[0]];
        gl.glGetShaderInfoLog(shader, logLength[0], (int[])null, 0, log, 0);

        System.err.println("Error compiling the shader: " + new String(log));
        System.exit(1);
    }

    return shader;
}

I do not know what function to call the two shaders, to generate this triangle with three vertices and each vertex defining the colors red, blue and green.

Shader.frag

 #version 400 core

 in vec4 varying_Color; // incoming varying data to the
                   // fragment shader
                   // sent from the vertex shader

 void main (void) {
 gl_FragColor = varying_Color;
 }

shader.vert

#version 400 core

in vec4 attribute_Position; // vertex shader
in vec4 attribute_Color; // attributes

out vec4 varying_Color; // Outgoing varying data
                    // sent to the fragment shader
void main (void) {
varying_Color = attribute_Color;
gl_Position = attribute_Position;
}

Body:
I do not use JAVA nor JOGL either so I may be wrong but my OpenGL experience is telling me that your vertex shader does not look OK to me especially this:

#version 400 core
in vec4 attribute_Position; // vertex shader
in vec4 attribute_Color; // attributes

You chose GL 4.00 core profile and using in as an input. That would work if your input was provided from shader above vertex but I think that is not the case (as you got only vertex and fragment) so you should have something like this instead:

#version 400 core
layout(location=0) in vec4 attribute_Position;
layout(location=1) in vec4 attribute_Color;

Also you should bind position and color VBO to these locations so unrem your

gl.glBindAttribLocation(shaderProgram, 0, "attribute_Position");
gl.glBindAttribLocation(shaderProgram, 1, "attribute_Color");

bindings in the code but I am not familiar with that I am more used to this:

// bind VBO
glBindBuffer(vbotype,vboid);
glEnableVertexAttribArray(vbolocation);
glVertexAttribPointer(vbolocation,datacomponents,datatype,GL_FALSE,0,0);

// unbind VBO
glBindBuffer(vbotype,0);
glDisableVertexAttribArray(vbolocation);

Where each VBO has these:

GLuint vboid;                       // OpenGL id for current VBO
int    vbolocation;                 // intended VBO atrib layout location for GLSL
GLuint vbotype;                     // GL_ARRAY_BUFFER,GL_ELEMENT_ARRAY_BUFFER
GLuint datatype;                    // GL_FLOAT,GL_UNSIGNED_INT
GLuint datacomponents;              // vector size 1,2,3,4
List<GLint> data;                   // 32bit vbo data (always overtype with datatype on any access!!!)


问:
toggleClass not working
I'm having problem with 'toggleClass'. What this script do is it adds a new set of field depending on the radio buttons value. Inside the field is a new div that is hidden by default and will be displayed only if the 'a' is triggered by a click event. At first it works but once I click on another radio button or at the same radio button the 'toggleClass' dont work anymore.

here is the code:

```<code>$(document).ready(function(){

      $('.duplicatorRadio').click(function() {
          var this_index_limit = parseInt($(this).val());
          for(var i = 0; i < this_index_limit; i++) {
             if(!$('#text_box_' + i).length) {
                var headerValue = parseInt(i) + 1;
                $(
                  '<fieldset id="text_box_' + i + '"> <h3>Property ' + headerValue +' Information</h3> <a class="borrowerToggler" href="#">Show Co-Borrower</a> <div class="borrower hide"> <h5>Co-Borrower Information</h5></div></fieldset>'
                  ).appendTo($(this).parent());
             }
             else if($('#text_box_' + i).css('display') == 'none') {
                $('#text_box_' + i).show();
             }
          }

          $('fieldset').each(function() {
             var split_id = $(this).attr('id').split('_');
             if(!split_id.length) return;
             var index = parseInt(split_id[2]);
             if(index >= this_index_limit) {
                 $(this).hide();
             }
          });

          $("a.borrowerToggler").click(function(){
            $(this).next("div").toggleClass("hide");
          });

      });

  });
</code>```

答: Try by using .live() method to bind click event. This demo might hlp you.

ContentLicense: CC BY-SA 2.5

Title: toggleClass not working

Body:
I'm having problem with 'toggleClass'. What this script do is it adds a new set of field depending on the radio buttons value. Inside the field is a new div that is hidden by default and will be displayed only if the 'a' is triggered by a click event. At first it works but once I click on another radio button or at the same radio button the 'toggleClass' dont work anymore.

here is the code:

$(document).ready(function(){

      $('.duplicatorRadio').click(function() {
          var this_index_limit = parseInt($(this).val());
          for(var i = 0; i < this_index_limit; i++) {
             if(!$('#text_box_' + i).length) {
                var headerValue = parseInt(i) + 1;
                $(
                  '<fieldset id="text_box_' + i + '">
Property ' + headerValue +' Information
 Show Co-Borrower

Co-Borrower Information

</fieldset>'
                  ).appendTo($(this).parent());
             }
             else if($('#text_box_' + i).css('display') == 'none') {
                $('#text_box_' + i).show();
             }
          }

          $('fieldset').each(function() {
             var split_id = $(this).attr('id').split('_');
             if(!split_id.length) return;
             var index = parseInt(split_id[2]);
             if(index >= this_index_limit) {
                 $(this).hide();
             }
          });

          $("a.borrowerToggler").click(function(){
            $(this).next("div").toggleClass("hide");
          });

      });

  });


问:
Remove all child elements of a DOM node in JavaScript
How would I go about removing all of the child elements of a DOM node in JavaScript?

Say I have the following (ugly) HTML:

    hello

world

```
<p>And I grab the node I want like so:</p>
```var myNode = document.getElementById("foo");
```
<p>How could I remove the children of <code>foo</code> so that just <code><p id="foo"></p></code> is left?</p>
<p>Could I just do:</p>
```myNode.childNodes = new Array();
```

or should I be using some combination of removeElement?

I'd like the answer to be straight up DOM; though extra points if you also provide an answer in jQuery along with the DOM-only answer.

答:
This is a pure javascript i am not using jQuery but works in all browser even IE and it is verry simple to understand</p>

```<code>   <div id="my_div">
    <p>Paragraph one</p>
    <p>Paragraph two</p>
    <p>Paragraph three</p>
   </div>
   <button id ="my_button>Remove nodes ?</button>

   document.getElementById("my_button").addEventListener("click",function(){

  let parent_node =document.getElemetById("my_div"); //Div which contains paagraphs

  //Let find numbers of child inside the div then remove all
  for(var i =0; i < parent_node.childNodes.length; i++) {
     //To avoid a problem which may happen if there is no childNodes[i]
     try{
       if(parent_node.childNodes[i]){
         parent_node.removeChild(parent_node.childNodes[i]);
       }
     }catch(e){
     }
  }

})

or you may simpli do this which is a quick way to do

document.getElementById("my_button").addEventListener("click",function(){

 let parent_node =document.getElemetById("my_div");
 parent_node.innerHTML ="";

})
</code>```

ContentLicense: CC BY-SA 4.0

Body:
How would I go about removing all of the child elements of a DOM node in JavaScript?

Say I have the following (ugly) HTML:

    hello

world

And I grab the node I want like so:

var myNode = document.getElementById("foo");

How could I remove the children of foo so that just

 is left?

Could I just do:

myNode.childNodes = new Array();

or should I be using some combination of removeElement?

I'd like the answer to be straight up DOM; though extra points if you also provide an answer in jQuery along with the DOM-only answer.

Body:
This is a pure javascript i am not using jQuery but works in all browser even IE and it is verry simple to understand

   <div id="my_div">
    <p>Paragraph one</p>
    <p>Paragraph two</p>
    <p>Paragraph three</p>
   </div>
   <button id ="my_button>Remove nodes ?</button>

   document.getElementById("my_button").addEventListener("click",function(){

  let parent_node =document.getElemetById("my_div"); //Div which contains paagraphs

  //Let find numbers of child inside the div then remove all
  for(var i =0; i < parent_node.childNodes.length; i++) {
     //To avoid a problem which may happen if there is no childNodes[i]
     try{
       if(parent_node.childNodes[i]){
         parent_node.removeChild(parent_node.childNodes[i]);
       }
     }catch(e){
     }
  }

})

or you may simpli do this which is a quick way to do

document.getElementById("my_button").addEventListener("click",function(){

 let parent_node =document.getElemetById("my_div");
 parent_node.innerHTML ="";

})


问:
Pass additional props to a react component
I would like to know how to pass additional props to an already defined React component, or if it is possible at all.

For instance, given,

```<code>const foo = (
  <Foo
    bar={bar}
  />
);
</code>```

Having defined foo like above, Can I later expand the prop list of foo programmatically to include baz? i.e. as if I did the following to begin with?

```<code>const foo = (
  <Foo
    bar={bar}
    baz={baz}
  />
);
</code>```

答:
You can do it programatically in the following manner

```<code>constructor() {
    super();
    this.state = {
         data: {bar: "bar"}
    }
}
</code>```

And then pass it to you compoenent using spread operator like

```<code>const foo = (
  <Foo
    {...this.state.data}
  />
);
</code>```

Later if you wan to add another prop you can just update the state data to have another property like

```<code>addData = () => {
    var data = {...this.state.data}
    data["baz"] = "baz"
    this.setState({data})
}
</code>```

And now since you have passed the props ...this.state.data

you can access them in you child component like this.props.bar and this.props.baz

Body:
I would like to know how to pass additional props to an already defined React component, or if it is possible at all.

For instance, given,

const foo = (
  <Foo
    bar={bar}
  />
);

Having defined foo like above, Can I later expand the prop list of foo programmatically to include baz? i.e. as if I did the following to begin with?

const foo = (
  <Foo
    bar={bar}
    baz={baz}
  />
);

Body:
You can do it programatically in the following manner

constructor() {
    super();
    this.state = {
         data: {bar: "bar"}
    }
}

And then pass it to you compoenent using spread operator like

const foo = (
  <Foo
    {...this.state.data}
  />
);

Later if you wan to add another prop you can just update the state data to have another property like

addData = () => {
    var data = {...this.state.data}
    data["baz"] = "baz"
    this.setState({data})
}

And now since you have passed the props ...this.state.data

you can access them in you child component like this.props.bar and this.props.baz


问:
C writing Linked List into file
I am trying to write linked list to file. I have a problem when adding new element.
Main problem is when assigning struct (read from file) to new_node->next_node, only pointer saved into new_node->next_node.
After i read from the file, try to print then first struct value was printed well and then second value (node_trx->next_node) was printed wrong. I need to store values not pointer to node_trx->next_node.
So is there anyone who can tell what did i wrong?

Here is my struct:

```<code>typedef struct {
    char amount[12];
    int currency;
    struct node_trx * next_node;
} node_trx;
</code>```

Here is add new element code:

```<code> node_trx * trx_list;
 if (3 != read_last_trx_from_file(EMVP_LAST_TRANSACTION_OBJECT, &trx_list, &data_set_len)) {
    if (NULL == (f = fopen(tools_get_full_filename_const(EMVP_LAST_TRANSACTION_OBJECT), "w+"))) {
        log_ntrx_error(-1, "Cannot open ticket data set file: %s.",
                strerror(errno));
    } else {
        node_trx * new_node = calloc(1, sizeof(node_trx));

        strcpy(new_node->amount, disp_amount);

        new_node->currency = currency_code;

        memcpy(&new_node->next_node, &trx_list, sizeof trx_list);

        if (1 != fwrite(new_node, data_set_len + sizeof(node_trx), 1, f)) {
            //error
        }

        free(new_node);
        free(trx_list);
        fclose(f);
    }
} else {
    // Saving first element
    if (NULL == (f = fopen(tools_get_full_filename_const(EMVP_LAST_TRANSACTION_OBJECT), "w")))
    {
        log_ntrx_error(-1, "Cannot open ticket data set file: %s.",
                strerror(errno));
    } else {
        trx_list = BKS_XCALLOC(1, sizeof(node_trx));

        strcpy(trx_list->amount, disp_amount);

        trx_list->currency = currency_code;
        trx_list->next_node = NULL;

        if (1 != fwrite(trx_list, sizeof(node_trx), 1, f)) {

        }

        fclose(f);
    }
</code>```

Here is file reading function:

```<code>int read_last_trx_from_file (const char * file_name, node_trx * * trx, unsigned * trx_len)
{
    FILE * f;
    *trx = NULL;

    if (NULL == (f = fopen(tools_get_full_filename_const(file_name), "rb")))
    {

    }

    size_t fsize;
    fseek(f, 0, SEEK_END);
    fsize = ftell(f);
    fprintf(stdout, "file size: %zd\n", fsize);
    if (!fsize)
    {
        return 3; // No data
    } else {
        if (fsize == 1) {
            return 3; // No data
        }
    }

    rewind(f);
    if (NULL != (*trx = (node_trx *) BKS_XCALLOC(1, fsize)))
    {
        if (1 != fread(*trx, fsize, 1, f))
        {
            fclose(f);
            return 2;
        }
    }
    fclose(f);

    *trx_len = fsize;
    return 0;
}
</code>```

Here is my printing data from file code:

```<code> node_trx * card_data;
 if (3 != read_last_trx_from_file(LAST_TRX_OBJECT, &card_data, &data_set_len)) {
 while (card_data->next_node != NULL) {
     strcpy(amount, card_data->amount);
     printf("%s AMOUNT \n", amount);
     printf("%d CURRENCY \n", card_data->currency);
     card_data = card_data->next_node;
 }
}
</code>```

答: If the linked list is sequential, you could just store the elements in order they occur.</p>

Title: C writing Linked List into file

Body:
I am trying to write linked list to file. I have a problem when adding new element.
Main problem is when assigning struct (read from file) to new_node->next_node, only pointer saved into new_node->next_node.
After i read from the file, try to print then first struct value was printed well and then second value (node_trx->next_node) was printed wrong. I need to store values not pointer to node_trx->next_node.
So is there anyone who can tell what did i wrong?

Here is my struct:

typedef struct {
    char amount[12];
    int currency;
    struct node_trx * next_node;
} node_trx;

Here is add new element code:

 node_trx * trx_list;
 if (3 != read_last_trx_from_file(EMVP_LAST_TRANSACTION_OBJECT, &trx_list, &data_set_len)) {
    if (NULL == (f = fopen(tools_get_full_filename_const(EMVP_LAST_TRANSACTION_OBJECT), "w+"))) {
        log_ntrx_error(-1, "Cannot open ticket data set file: %s.",
                strerror(errno));
    } else {
        node_trx * new_node = calloc(1, sizeof(node_trx));

        strcpy(new_node->amount, disp_amount);

        new_node->currency = currency_code;

        memcpy(&new_node->next_node, &trx_list, sizeof trx_list);

        if (1 != fwrite(new_node, data_set_len + sizeof(node_trx), 1, f)) {
            //error
        }

        free(new_node);
        free(trx_list);
        fclose(f);
    }
} else {
    // Saving first element
    if (NULL == (f = fopen(tools_get_full_filename_const(EMVP_LAST_TRANSACTION_OBJECT), "w")))
    {
        log_ntrx_error(-1, "Cannot open ticket data set file: %s.",
                strerror(errno));
    } else {
        trx_list = BKS_XCALLOC(1, sizeof(node_trx));

        strcpy(trx_list->amount, disp_amount);

        trx_list->currency = currency_code;
        trx_list->next_node = NULL;

        if (1 != fwrite(trx_list, sizeof(node_trx), 1, f)) {

        }

        fclose(f);
    }

Here is file reading function:

int read_last_trx_from_file (const char * file_name, node_trx * * trx, unsigned * trx_len)
{
    FILE * f;
    *trx = NULL;

    if (NULL == (f = fopen(tools_get_full_filename_const(file_name), "rb")))
    {

    }

    size_t fsize;
    fseek(f, 0, SEEK_END);
    fsize = ftell(f);
    fprintf(stdout, "file size: %zd\n", fsize);
    if (!fsize)
    {
        return 3; // No data
    } else {
        if (fsize == 1) {
            return 3; // No data
        }
    }

    rewind(f);
    if (NULL != (*trx = (node_trx *) BKS_XCALLOC(1, fsize)))
    {
        if (1 != fread(*trx, fsize, 1, f))
        {
            fclose(f);
            return 2;
        }
    }
    fclose(f);

    *trx_len = fsize;
    return 0;
}

Here is my printing data from file code:

 node_trx * card_data;
 if (3 != read_last_trx_from_file(LAST_TRX_OBJECT, &card_data, &data_set_len)) {
 while (card_data->next_node != NULL) {
     strcpy(amount, card_data->amount);
     printf("%s AMOUNT \n", amount);
     printf("%d CURRENCY \n", card_data->currency);
     card_data = card_data->next_node;
 }
}


问:
NSGridView not available in Storyboard?
I want to use a NSGridView to build a preferences window but it seems that I can't use/layout it in the Storyboard. Am I missing something?</p>

答: NSGridView is available in Interface Builder starting with Xcode 10.</p>

Title: NSGridView not available in Storyboard?


问:
What is the difference between the methods PutExtra and PutExtras in Android?
What is the difference between PutExtra() method and PutExtras() method in Android?

答:
putExtra contains a key-value pair

putExtras contains a bundle which is a map(contains multiple key-value pairs)


问:
grails won't save but have no error
Hi I have a domain that so simple like the following

```<code>// page 52 Bankruptcy Questions
class FamilyLawFinancial{

    Date dateOfTheOrder ;
    boolean isPartyToFamilyLawProperty = false;
    boolean isCurrentlyInvolvedInFamilyLawProperty = false;
    boolean isBecomeInvolvedInProceedings = false;

    static belongsTo=[person:Person];

    static constraints = {
        dateOfTheOrder(nullable:true);
        isPartyToFamilyLawProperty(nullable:false);
        isCurrentlyInvolvedInFamilyLawProperty(nullable:false);
        isBecomeInvolvedInProceedings(nullable:false);
    }

    String toString(){
        "${id}"
    }
}
</code>```

and here is the controller that save the data:

```<code>    def save = {
    def person = Person.get(session.curperson.id);
    def obj = FamilyLawFinancial.findByPerson(person);
    if(obj == null){
        obj = new FamilyLawFinancial();
        obj.person = person ;
    }
    params.dateOfTheOrder = myutil.formatDate(params.dateOfTheOrder);
    obj.properties = params;

    println(obj.hasErrors());
    println(obj.dateOfTheOrder);
    if(obj.hasErrors() && !obj.save(flush:true)){
        println("errors: ${obj.errors}");
        flash.message = "error found";
        println("save familyLawFinancial errors: ${errors}");
    }else{
        flash.message = "saved ";
    }
    redirect(controller:'frontPage', action:'index'); return ;
}
</code>```

The obj.hasErrors() produce false (it means no error) but it wont save into the database. Any idea how to debug this ?

ps: myutil.formatDate() --> for converting the Date String such as 19/11/2010 to Date()

答:
```<code>if(obj.hasErrors() && !obj.save(flush:true)){
</code>```

The condition after && will not be evaluated if the condition before evaluates to false.

As false && true evaluates to false, evaluating the second condition would be inefficient from the language's point of view.

After all, in this case, obj.save(..) never gets called.

Title: grails won't save but have no error

Body:
Hi I have a domain that so simple like the following

// page 52 Bankruptcy Questions
class FamilyLawFinancial{

    Date dateOfTheOrder ;
    boolean isPartyToFamilyLawProperty = false;
    boolean isCurrentlyInvolvedInFamilyLawProperty = false;
    boolean isBecomeInvolvedInProceedings = false;

    static belongsTo=[person:Person];

    static constraints = {
        dateOfTheOrder(nullable:true);
        isPartyToFamilyLawProperty(nullable:false);
        isCurrentlyInvolvedInFamilyLawProperty(nullable:false);
        isBecomeInvolvedInProceedings(nullable:false);
    }

    String toString(){
        "${id}"
    }
}

and here is the controller that save the data:

    def save = {
    def person = Person.get(session.curperson.id);
    def obj = FamilyLawFinancial.findByPerson(person);
    if(obj == null){
        obj = new FamilyLawFinancial();
        obj.person = person ;
    }
    params.dateOfTheOrder = myutil.formatDate(params.dateOfTheOrder);
    obj.properties = params;

    println(obj.hasErrors());
    println(obj.dateOfTheOrder);
    if(obj.hasErrors() && !obj.save(flush:true)){
        println("errors: ${obj.errors}");
        flash.message = "error found";
        println("save familyLawFinancial errors: ${errors}");
    }else{
        flash.message = "saved ";
    }
    redirect(controller:'frontPage', action:'index'); return ;
}

The obj.hasErrors() produce false (it means no error) but it wont save into the database. Any idea how to debug this ?

ps: myutil.formatDate() --> for converting the Date String such as 19/11/2010 to Date()

Body:
if(obj.hasErrors() && !obj.save(flush:true)){

The condition after && will not be evaluated if the condition before evaluates to false.

As false && true evaluates to false, evaluating the second condition would be inefficient from the language's point of view.

After all, in this case, obj.save(..) never gets called.


问:
Jquery addClass is not working?
When I click on any categories it is adding class as "active", but when I click on other, then categories it is refreshing and class is removed. how to resolve this?

Below is HTML code,

```<code><div class="flDropDiv category_fl">
                            <div class="flItems"><a class="category_filter" data-value="Fitted bed Sheet " href="http://192.168.1.156/eles/bed-linen/fitted-bed-sheet"> Fitted bed Sheet  </a> </div>
                            <div class="flItems"><a class="category_filter" data-value="Flat bed sheet " href="http://192.168.1.156/eles/bed-linen/flat-bed-sheet"> Flat bed sheet  </a> </div>
                            <div class="flItems"><a class="category_filter" data-value="Full bed sheets  " href="http://192.168.1.156/eles/bed-linen/full-bed-sheets"> Full bed sheets   </a> </div>
                            <div class="flItems"><a class="category_filter" data-value="Twin bed sheet " href="http://192.168.1.156/eles/bed-linen/twin-bed-sheet"> Twin bed sheet  </a> </div>
                            <div class="flItems"><a class="category_filter" data-value="Twinxl bed sheets  " href="http://192.168.1.156/eles/bed-linen/twinxl-bed-sheets"> Twinxl bed sheets   </a> </div>
                            <div class="flItems"><a class="category_filter" data-value="Queen bed sheet " href="http://192.168.1.156/eles/bed-linen/queen-bed-sheet"> Queen bed sheet  </a> </div>
                            <div class="flItems"><a class="category_filter" data-value="King bed sheets " href="http://192.168.1.156/eles/bed-linen/king-bed-sheets"> King bed sheets  </a> </div>
                            <div class="flItems"><a class="category_filter" data-value="Cal king bed sheets " href="http://192.168.1.156/eles/bed-linen/cal-king-bed-sheets"> Cal king bed sheets  </a> </div>
                            <div class="flItems"><a class="category_filter" data-value="Duvet covers " href="http://192.168.1.156/eles/bed-linen/duvet-covers"> Duvet covers  </a> </div>
                            <div class="flItems"><a class="category_filter" data-value="Bed skirts " href="http://192.168.1.156/eles/bed-linen/bed-skirts"> Bed skirts  </a> </div>
                            <div class="flItems"><a class="category_filter" data-value="Standard Pillow cases " href="http://192.168.1.156/eles/bed-linen/standard-pillow-cases"> Standard Pillow cases  </a> </div>
                            <div class="flItems"><a class="category_filter" data-value="King Pillow cases " href="http://192.168.1.156/eles/bed-linen/king-pillow-cases"> King Pillow cases  </a> </div>
                            <div class="flItems"><a class="category_filter" data-value="Pillow shells " href="http://192.168.1.156/eles/bed-linen/pillow-shells"> Pillow shells  </a> </div>
                        </div>
</code>```

Jquery Code,

```<code>    var localStorageIndex = "clickedLink";
$(function() {
  $(".category_filter").click(function(e) {
    if($(e.target).hasClass("active")){
    return;
    }
    var clickedLink = getActiveLinkFromLocalStorage();
    if(clickedLink !== e.target.href){
      clickedLink = e.target.href;
      $(e.target).addClass("active");
      localStorage.setItem(localStorageIndex, clickedLink);
    }
  })

  function getActiveLinkFromLocalStorage() {
    return localStorage.getItem(localStorageIndex);
  }

  function initActiveLink(){
    var clickedLink = getActiveLinkFromLocalStorage();
    if(!clickedLink){
      return;
    }
      localStorage.clear();
      $("a[href='" + clickedLink + "'].category_filter").addClass("active");
  }
  initActiveLink();
});
</code>```

答:
it's refreshing because u field href with url. if you need url link ucan use attribute for helping you know the uri on tag . this a simple example to add class hactive on class "category_filter"

 $(document).ready(function () {
   $(document).on("click",".category_filter", function(){
     /* to remove class, uncomment this if you want to remove class $(".category_filter").removeClass("hactive");*/

   //if you want to get the uri data u can use;
   var uriData = $(this).attr("data-uriex");
   $(this).addClass("hactive");

   //sample view the single uri when click.
   $("#justClick").html("uri data click : "+uriData);

   //sample for get all uri on hactive class;
   var cekData = "", i =0;
   $(".hactive").each(function(){
     cekData = cekData+"data URI Active: "+(i+1)+" "+$(this).attr("data-uriex")+"
";i++;
   });
   $("#AllUri").html(cekData);
  });
 });```
<pre class="snippet-code-css lang-css prettyprint-override"><code> .hactive{
  color : #f00;
 }</code>```

   Fitted bed Sheet

   Flat bed sheet

     Full bed sheets

    Twin bed   sheet

```

Title: Jquery addClass is not working?

Body:
When I click on any categories it is adding class as "active", but when I click on other, then categories it is refreshing and class is removed. how to resolve this?

Below is HTML code,

 Fitted bed Sheet

 Flat bed sheet

 Full bed sheets

 Twin bed sheet

 Twinxl bed sheets

 Queen bed sheet

 King bed sheets

 Cal king bed sheets

 Duvet covers

 Bed skirts

 Standard Pillow cases

 King Pillow cases

 Pillow shells

Jquery Code,

    var localStorageIndex = "clickedLink";
$(function() {
  $(".category_filter").click(function(e) {
    if($(e.target).hasClass("active")){
    return;
    }
    var clickedLink = getActiveLinkFromLocalStorage();
    if(clickedLink !== e.target.href){
      clickedLink = e.target.href;
      $(e.target).addClass("active");
      localStorage.setItem(localStorageIndex, clickedLink);
    }
  })

  function getActiveLinkFromLocalStorage() {
    return localStorage.getItem(localStorageIndex);
  }

  function initActiveLink(){
    var clickedLink = getActiveLinkFromLocalStorage();
    if(!clickedLink){
      return;
    }
      localStorage.clear();
      $("a[href='" + clickedLink + "'].category_filter").addClass("active");
  }
  initActiveLink();
});

Body:
it's refreshing because u field href with url. if you need url link ucan use attribute for helping you know the uri on tag . this a simple example to add class hactive on class "category_filter"

 $(document).ready(function () {
   $(document).on("click",".category_filter", function(){
     /* to remove class, uncomment this if you want to remove class $(".category_filter").removeClass("hactive");*/

   //if you want to get the uri data u can use;
   var uriData = $(this).attr("data-uriex");
   $(this).addClass("hactive");

   //sample view the single uri when click.
   $("#justClick").html("<b>uri data click :</b> "+uriData);

   //sample for get all uri on hactive class;
   var cekData = "", i =0;
   $(".hactive").each(function(){
     cekData = cekData+"data URI Active: "+(i+1)+" "+$(this).attr("data-uriex")+"<br/>";i++;
   });
   $("#AllUri").html(cekData);
  });
 });

 .hactive{
  color : #f00;
 }

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="flDropDiv category_fl">
 <div class="flItems">
  <a class="category_filter" data-value="Fitted bed Sheet " href="#"
   data-uriex="http://192.168.1.156/eles/bed-linen/fitted-bed-sheet">
   Fitted bed Sheet
  </a>
 </div>
 <div class="flItems">
  <a class="category_filter" data-value="Flat bed sheet " href="#" data-uriex="http://192.168.1.156/eles/bed-linen/flat-bed-sheet">
   Flat bed sheet
   </a>
 </div>
  <div class="flItems">
   <a class="category_filter" data-value="Full bed sheets"  href="#" data-uriex="http://192.168.1.156/eles/bed-linen/full-bed-sheets">
     Full bed sheets
   </a>
  </div>
  <div class="flItems">
   <a class="category_filter" data-value="Twin bed sheet"  href="#" data-uriex="http://192.168.1.156/eles/bed-linen/twin-bed-sheet">
    Twin bed   sheet
   </a>
  </div>
 </div>
 <div id="justClick"></div>
 <hr/>
<div id ="AllUri"></div>


问:
C# - HTTPWebRequest not returning anything
So without fiddler open, my code doesnt seem to do ANYTHING!
But with it open, it works fine?! What?

```<code>HttpWebRequest init = (HttpWebRequest)WebRequest.Create("https://accounts.spotify.com/en/login?continue=https:%2F%2Fwww.spotify.com%2Fus%2Faccount%2Foverview%2F");
init.Method = "GET";
init.UserAgent = "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36";
init.Timeout = 8000;
HttpWebResponse resp1 = (HttpWebResponse)init.GetResponse();
</code>```

The thread (In my case ThreadPool thread), will just freeze, not end, will just freeze as its not able to connect, and the try catch doesnt even seem to work either.

If I change the Port on Fiddlers Settings to anything other than 8888 and have Fiddler open, it starts to freeze again, meaning somewhere its linked to 8888 somehow. Yet its not referenced in my code at all.

FIXED!

Found out it was caused by not closing! resp1.close().
Thanks everyone!

答:
It's done right that, what you wrote in your code. Try debug this code and see what you get as a response, pay attention to responseBody and HtmlResult

```<code>HttpWebRequest init = (HttpWebRequest)WebRequest.Create("https://accounts.spotify.com/en/login?continue=https:%2F%2Fwww.spotify.com%2Fus%2Faccount%2Foverview%2F");
init.Method = "GET";
init.UserAgent = "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36";
init.Timeout = 8000;
HttpWebResponse resp1 = (HttpWebResponse)init.GetResponse();
HttpStatusCode sc = resp1.StatusCode;
String sd = resp1.StatusDescription;
string HtmlResult = "";
string responseBody = "";
using (System.IO.Stream rspStm = resp1.GetResponseStream())
{
    using (System.IO.StreamReader reader = new System.IO.StreamReader(rspStm))
    {
        HtmlResult = HtmlResult +
                "Response Description: " + resp1.StatusDescription;
        HtmlResult = HtmlResult +
                "Response Status Code: " + resp1.StatusCode;
        HtmlResult = HtmlResult + "\r\n\r\n";
        responseBody = reader.ReadToEnd();
    }
}
</code>```

Body:
So without fiddler open, my code doesnt seem to do ANYTHING!
But with it open, it works fine?! What?

HttpWebRequest init = (HttpWebRequest)WebRequest.Create("https://accounts.spotify.com/en/login?continue=https:%2F%2Fwww.spotify.com%2Fus%2Faccount%2Foverview%2F");
init.Method = "GET";
init.UserAgent = "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36";
init.Timeout = 8000;
HttpWebResponse resp1 = (HttpWebResponse)init.GetResponse();

The thread (In my case ThreadPool thread), will just freeze, not end, will just freeze as its not able to connect, and the try catch doesnt even seem to work either.

If I change the Port on Fiddlers Settings to anything other than 8888 and have Fiddler open, it starts to freeze again, meaning somewhere its linked to 8888 somehow. Yet its not referenced in my code at all.

FIXED!

Found out it was caused by not closing! resp1.close().
Thanks everyone!

Body:
It's done right that, what you wrote in your code. Try debug this code and see what you get as a response, pay attention to responseBody and HtmlResult

HttpWebRequest init = (HttpWebRequest)WebRequest.Create("https://accounts.spotify.com/en/login?continue=https:%2F%2Fwww.spotify.com%2Fus%2Faccount%2Foverview%2F");
init.Method = "GET";
init.UserAgent = "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36";
init.Timeout = 8000;
HttpWebResponse resp1 = (HttpWebResponse)init.GetResponse();
HttpStatusCode sc = resp1.StatusCode;
String sd = resp1.StatusDescription;
string HtmlResult = "";
string responseBody = "";
using (System.IO.Stream rspStm = resp1.GetResponseStream())
{
    using (System.IO.StreamReader reader = new System.IO.StreamReader(rspStm))
    {
        HtmlResult = HtmlResult +
                "Response Description: " + resp1.StatusDescription;
        HtmlResult = HtmlResult +
                "Response Status Code: " + resp1.StatusCode;
        HtmlResult = HtmlResult + "\r\n\r\n";
        responseBody = reader.ReadToEnd();
    }
}


问:
Google Script / Reducing execution time below exec time limit
EDIT#2:

I've decided to try and batch the copy-paste operations that run after all the emails are fired. In previous posted code, in the last lines of every loop, I copied and pasted the items from each purchase order ("Email" sheet) to another ("AsignRec"). Now, what I want to do is store the items from "Email" sheet in every loop to a Javascript array, and paste all together into "AsignRec" at the end, just once.

However, I'm still not doing it right. I'm stuck at the final pasting/setValues(). I believe the array is correctly formed, as it has a length of 49, which is the number of unique SKUs to be sent out to suppliers. Still, at the setValues([OCitems]) line 185, I get the error "Incorrect range height, was 1 but should be 49 (line 185, file "TestArrayMultiple4")".

I assume this means the destination/output range is not the same size as array/input (called OCitems). I don't see why though, since I defined the length of the output range using OCitems.length. I am missing something, and not sure what.

This is the important bit of the code, and full code below. Same GDocs link as before, script file TestArrayMultiple4, lines 160-185.
https://docs.google.com/spreadsheets/d/1yzvMTh0VYhRhiexNzQPIjTwz1FCMq4XnbpGvCF1FYu8/edit#gid=436022027

```<code>    /// Get Range we want to change to creating Javascript array and paste at end only

var OcNoHeader = sheet.getRange("B9:J" + MaxTableRow).getValues(); // get items to send to supplier from "Email Sheet"

// if supplier number is 1, create array "OCitems" by storing OcNoHeader. If not supplier #1, then append to existing array "OCitems"

  if(y == 1){
    var OCitems = OcNoHeader}
    else
      {for(j=0;j<OcNoHeader.length;j++){
      OCitems.push(OcNoHeader[j]);
  }}

  Logger.log(OCitems);
  Logger.log("OCitems length = " + OCitems.length)

  debugger;

i++; // after firing email, y+1 to go to next supplier
Logger.log("i++ IF =" + 1);

Logger.log("new i ELSE =" + 1)

debugger;

} // only do while x = max number of suppliers reached
  while (i < x);

  sheet3.getRange(3, 3, OCitems.length, 9).setValues([OCitems]); // paste operation, NumRows set equal to length of array
</code>```

=========================

EDIT#1: Worked on improving performance using getValues of several cells instead of doing individual getValue() several times over. Unfortunately, this hasn't reduced the execution time in a stable or noticeable manner (sometimes it finished before 6min, sometimes not).

Posting code below (you can access it in script file "TestArrayMultiple2" in new Sheet shared below):

Using Execution transcript, I see that although the execution time of the getValue() lines that were previously taking very long has basically been reduced to zero, other lines of code are now taking more time and killing the gain achieved from the batching other getValue().

There are still 4-5 "individual" getValue() on specific cells (much less than before), but I don't understand why they would take so long. So it seems even if I removed the remaining "individual" getValue(), if only one remained, it would take even longer.

Seems to me it has something to do with caching (and I'm sure I don't fully understand this concept), for the following reasons:
1) It is always the first getValue() in the loop which takes the longest.
2) I tried to go down a different route, by changing the code for the copy/paste operation which occurrs after all emails are sent (line 150 in "TestArrayMultiple2" script file). I basically try to create an array which gets fed with more data at every loop (append/push method) but doesn't paste within every loop - the idea is to paste all the data at the end, after finishing looping. I still don't have it right (this second script file is the last one, "TestArrayMultiple3"), but I can see the emails get fired off much faster.

Once again, your help would be much appreciated.

```<code>> // version with 1 getDataRange array which stores for supplier ID, name, email, MaxTableRow for PO email, email subject all from Dashboard sheet

function TestArrayMultiple2() {

  var ss = SpreadsheetApp.getActiveSpreadsheet ();
  var sheet = ss.getSheetByName("Email");
  var sheet1 = ss.getSheetByName("Pedido email");
  var sheet2 = ss.getSheetByName("Dashboard");
  var sheet3 = ss.getSheetByName("AsignRec");
  var sheet4 = ss.getSheetByName("ListadoProductos");
  var sheet5 = ss.getSheetByName("Registro-Consolid");
  var sheet6 = ss.getSheetByName("Registro-Unico");

  var x = ss.getSheetByName("Dashboard").getRange("C4").getValue();
  Logger.log("x = " + x)

  var offsetV = 4; // number of rows of offset for email status to be inserted in Dashboard sheet

  var OffSetColProv = 1; // column in Dashboard sheet with supplier name
  var OffsetColMaxPOrows = 3; // Number of unique SKUs or rows in PO. Replace MaxTableRow formula in Email Sheet
  var OffSetColPzas = 4; // column in Dashboard sheet with number of items in supplier purchase order.
  var OffSetColEmail = 5; // column in Dashboard sheet with supplier email
  var OffSetColCC = 13; // column in Dashboard sheet with supplier email CC
  var OffSetColSubject = 14; // column in Dashboard sheet with supplier email Subject

  var colStatus = 11; // column in Dashboard sheet where send status of email inserted -----> LEAVE AS IS FOR NOW, not an offset, is fixed, col. K = 11
  var OffsetEmailRows = 8 // number of rows in Email sheet before the items in PO are shown

  var ProvNumEmail = sheet.getRange(1,2); // Supplier number in email sheet used to refresh products in purchase order email via FILTER formula

  var StatusRange = sheet2.getRange("K5:K100");
  Logger.log("StatusRange = " + StatusRange)

  var currentTime =  new Date();
  var timestamp = Utilities.formatDate(currentTime,'GMT-0600','dd/MM/yyyy HH:mm:ss');
  Logger.log("timestamp = " + timestamp);

  var ProvArray = sheet2.getRange("E5:S100");
  var DashValues = ProvArray.getValues();

  i = 0;

  do {

  var y = DashValues[i][0];
  Logger.log("y = " + y)

  ProvNumEmail.setValue(y);   // set value of next supplier in Email sheet to load next purchase order products

    // emails var here in order to update email value in IF email = ERROR condition and skip to else

  var Prov = DashValues[i][OffSetColProv];
  Logger.log("Prov = " + Prov);

  var EmailSubject = DashValues[i][OffSetColSubject];
  Logger.log("EmailSubject = " + EmailSubject)

  var MaxTableRow = DashValues[i][OffsetColMaxPOrows] + OffsetEmailRows;
  Logger.log("MaxTableRow = " + MaxTableRow)

  var EmailTo = DashValues[i][OffSetColEmail];
  Logger.log("EmailTo = " + EmailTo)

  var EmailCC = DashValues[i][OffSetColCC];
  Logger.log("EmailCC = " + EmailCC)

  var Piezas = DashValues[i][OffSetColPzas];
  Logger.log("Piezas = " + Piezas)

  SpreadsheetApp.flush();

  var name = "Petsy Compras - Juan Carlos León";
  var ReplyToEmail = "compras@petsy.mx";
  var email = EmailTo;
  var subject = EmailSubject;
  var name = name;
  var replyTo = ReplyToEmail;
  var Emailcc = EmailCC;
  var schedRange = sheet.getRange("B7:J"+MaxTableRow);
  var body = '<div>';
    body += "Estimados," +'<br>' + '<br>';
    body += "Envío la orden de compra, por un total de " + '<b>' + Piezas + " piezas." + '</b>' +'<br>' + '<br>';
    body += "Favor de confirmar las existencias lo más rápidamente posible, dentro del mismo correo y"+ '<b><a style="color:#FF0000">'+ " enviar factura a: "+ '</a></b>' + "facturasproveedores@petsy.mx." +'<br>' + '<br>';
    body += "Al dar " +'<b><a style="color:#FF0000"> '+ "RESPONDER A TODOS" + '</a></b>' +" la tabla con los productos pedidos se hace editable: favor de marcar por cada item si será faltante." +'<br>' + '<br>';
    body += "Cualquier duda avísenme por favor." +'<br>' + '<br>';
    body += "Un saludo" +'<br>' + '<br>';
    body += '<b>'     + "Juan Carlos León" + '<b>' + '<br>';
    body += "Petsy Compras"+'<br>';
    body += "Mapa aquí: "+'<br>';
    body += "Fijo directo 1: (55) 68 12 07 97 / Fijo directo 2: (55) 68 12 07 99 / Cel y Whatsapp: 55 32 23 57 17"+'<br>' + '<br>';
    body += "" +'<br>' + '<br>';
    body += getHtmlTable(schedRange);
    body += '</div>';

  // variables for error email

  var emailERR = 'oscialom@petsy.mx'
  var subjectERR = 'ERROR ENVIO OC' + ' // ' + Prov + ' ' + timestamp

  if(email == 'ERROR' || MaxTableRow == 0) // skip condition to go begin loop with y+1

{

// if above skip condition is true, y+1 to move to next purchase order

  Logger.log("y = " + y);
  Logger.log("IF");
  sheet2.getRange(y + offsetV,colStatus).setValue('NOT_SENT'); // set email send status next to supplier in Dashboard sheet
  {
     GmailApp.sendEmail(emailERR, subjectERR, "Requires HTML",
                {
                    'name':name,
                    'replyTo':replyTo,
                    'htmlBody':'',
                    'cc':''});
        }

  i++;

  Logger.log("new i IF =" + 1);
  continue

}
else
{

  // if skip condition is false, fire current supplier purchase order email email

  Logger.log("i = " + i);
  Logger.log("y = " + y);
  Logger.log("ELSE");

  GmailApp.sendEmail(email, subject, "Requires HTML",
                {
                    'name':name,
                    'replyTo':replyTo,
                    'htmlBody':body,
                    'cc':EmailCC});
        }

sheet2.getRange(y + offsetV,colStatus).setValue('OK'); // set email send status next to supplier in Dashboard sheet

// START copy-paste Asign-Rec

var MaxTableRowASIGN = sheet3.getRange("A1").getValue();
Logger.log("MaxTableRowASIGN = " + MaxTableRowASIGN)

/// Get Range we want to change to creating Javascript array and paste at end only

  debugger; // stop debugger at this point !! REMOVE OR PLACE AT CORRECT LINE IF USING DEBUGGER

var OcNoHeader = sheet.getRange("B9:J" + MaxTableRow);
var ConsolAsignRec = sheet3.getRange("B3:K" + MaxTableRow);
var ProvOC = sheet.getRange("B2").getValue();
Logger.log("ProvOC = " + ProvOC)

var MaxRowB = sheet3.getRange("C1").getValue() + 1;
Logger.log("MaxRowB = " + MaxRowB);

var NextRowB = MaxRowB + 1;
Logger.log("NextRowB = " + NextRowB);

OcNoHeader.copyTo(sheet3.getRange(MaxTableRowASIGN + 1,3),{contentsOnly:true});
var NumRowsProv = OcNoHeader.getNumRows();

var ProvOCcolumn = sheet3.getRange(MaxRowB, 2, NumRowsProv)
Logger.log("ProvOCcolumn = " + ProvOCcolumn);

ProvOCcolumn.setValue(ProvOC);

// END copy-paste Asign-Rec

i++; // after firing email, y+1 to go to next supplier
Logger.log("i++ IF =" + 1);

Logger.log("new i ELSE =" + 1)

} // only do while x = max number of suppliers reached
  while (y<x);

  // set y = 1 to reset value again after finishing loop

  sheet.getRange(1,2).setValue(1); // reset ProvNumber = 1 to start again next time script is fired.

  var EmailsSent = sheet2.getRange("C10").getValue(); // set values
  Logger.log("EmailsSent = " + EmailsSent)

  var EmailErrors = sheet2.getRange("C11").getValue();
  Logger.log("EmailErrors = " + EmailErrors)

  var MaxTableRowEND = sheet2.getRange("C9").getValue();
  var schedRange = sheet2.getRange("E4:K" + MaxTableRowEND);
  var emailEND = "oscialom@petsy.mx";
  var subjectEND = 'OCs Inbound enviadas' + ' ' + timestamp + " (errores " +  EmailErrors + " / enviados " + EmailsSent + ")";
  var EmailCCEND = "";
  var bodyEND = getHtmlTable(schedRange);

   GmailApp.sendEmail(emailEND, subjectEND, "Requires HTML",
                {
                    'name':name,
                    'replyTo':replyTo,
                    'htmlBody':bodyEND,
                    'cc':EmailCCEND});

StatusRange.clearContent();

/// START RecordTimestamp code

  var Avals = sheet4.getRange("A1:A").getValues();
  var lastrow1 = Avals.filter(String).length;
  Logger.log('lastrow1 =' + lastrow1)

  var Avals2 = sheet5.getRange("A1:A").getValues();
  var lastrow2 = Avals2.filter(String).length;
  Logger.log('lastrow2 =' + lastrow2)

    sheet4.getRange("B2:B" + lastrow1).copyTo(sheet5.getRange(lastrow2 + 1, 1)) // copy order-items to Registro sheet, after last filled row

    sheet4.getRange("K2:K" + lastrow1).copyTo(sheet5.getRange(lastrow2 + 1, 2)) // copy Prov1 to Registro sheet, after last filled row

  var Avals3 = sheet5.getRange("C1:C").getValues();
  var lastrow2c = Avals3.filter(String).length;
  Logger.log('lastrow2c =' + lastrow2c);

  if(lastrow2 == 1)
  { sheet5.getRange(lastrow2c + 1, 3, lastrow1 - 1).setValue(timestamp)
    Logger.log('IF')

    }

    else
    {
    sheet5.getRange(lastrow2c + 1, 3, lastrow1 - 1).setValue(timestamp)
    Logger.log('ELSE')
    }

var MaxTableRowEMAIL = sheet6.getRange("G5").getValue()

var subject = "Items pedidos en OC automatizada " + timestamp
var email = "oscialom@petsy.mx";
var EmailCC = "";
var EmailBCC;
var name = "Petsy Compras";
var ReplyToEmail = "compras@petsy.mx"
var schedRange = sheet6.getRange("A1:C" + MaxTableRowEMAIL);
var body = getHtmlTable(schedRange);

{
     GmailApp.sendEmail(email, subject, "Requires HTML",
                {
                    'name':name,
                    'replyTo':ReplyToEmail,
                    'htmlBody':body,
                    'cc':''});
        }

/// END RecordTimestamp code

Logger.log("MaxTableRowASIGN " + MaxTableRowASIGN);

var endtime = new Date();
Logger.log("timestamp end " + timestamp);
Logger.log("endtime " + Utilities.formatDate(endtime,'GMT-0600','dd/MM/yyyy HH:mm:ss'));

var scripttime = (endtime - currentTime);
Logger.log("scripttime original" + scripttime);

// strip the ms
scripttime /= 1000;
Logger.log("scripttime / 1000" + scripttime);

// get seconds (Original had 'round' which incorrectly counts 0:28, 0:29, 1:30 ... 1:59, 1:0)
var seconds = Math.round(scripttime % 60);
Logger.log("scripttime % 60" + scripttime);

// remove seconds from the date
scripttime = Math.floor(scripttime / 60);
Logger.log("scripttime / 60" + scripttime);

// Browser.msgBox("Script completado en " + seconds + " segundos",Browser.Buttons.OK_CANCEL); // removed MsgBox to measure real execution time
Logger.log("seconds " + seconds)

}
</code>```

=====================

ORIGINAL POST

I wrote a Google script to automate the purchase order process to several suppliers. The process takes a list of products (from sheet ListaProductos), formats the product info into an email format (sheet "Email"), sends the emails, and does some copy/pasting into other sheets of the same spreadsheet. However, I always run into the execution time at around 75% of the script. I'm fairly new to this, have been reading up but frankly don't know what to try next.

答:
I see the problem in this part of code:

```<code>do {
  // read info from the sheet
  range.getValue();
  // more code here...

} // only do while x = max number of suppliers reached
  while (y<x)
</code>```

Operation getValue takes much time to run. Best practice is to use the whole range:

```<code>var data = sheet.getDataRange().getValuses();
</code>```

and then use data as source for further calculations.

See more info here:

https://developers.google.com/apps-script/best_practices

Body:
EDIT#2:

I've decided to try and batch the copy-paste operations that run after all the emails are fired. In previous posted code, in the last lines of every loop, I copied and pasted the items from each purchase order ("Email" sheet) to another ("AsignRec"). Now, what I want to do is store the items from "Email" sheet in every loop to a Javascript array, and paste all together into "AsignRec" at the end, just once.

However, I'm still not doing it right. I'm stuck at the final pasting/setValues(). I believe the array is correctly formed, as it has a length of 49, which is the number of unique SKUs to be sent out to suppliers. Still, at the setValues([OCitems]) line 185, I get the error "Incorrect range height, was 1 but should be 49 (line 185, file "TestArrayMultiple4")".

I assume this means the destination/output range is not the same size as array/input (called OCitems). I don't see why though, since I defined the length of the output range using OCitems.length. I am missing something, and not sure what.

This is the important bit of the code, and full code below. Same GDocs link as before, script file TestArrayMultiple4, lines 160-185.
https://docs.google.com/spreadsheets/d/1yzvMTh0VYhRhiexNzQPIjTwz1FCMq4XnbpGvCF1FYu8/edit#gid=436022027

    /// Get Range we want to change to creating Javascript array and paste at end only

var OcNoHeader = sheet.getRange("B9:J" + MaxTableRow).getValues(); // get items to send to supplier from "Email Sheet"

// if supplier number is 1, create array "OCitems" by storing OcNoHeader. If not supplier #1, then append to existing array "OCitems"

  if(y == 1){
    var OCitems = OcNoHeader}
    else
      {for(j=0;j<OcNoHeader.length;j++){
      OCitems.push(OcNoHeader[j]);
  }}

  Logger.log(OCitems);
  Logger.log("OCitems length = " + OCitems.length)

  debugger;

i++; // after firing email, y+1 to go to next supplier
Logger.log("i++ IF =" + 1);

Logger.log("new i ELSE =" + 1)

debugger;

} // only do while x = max number of suppliers reached
  while (i < x);

  sheet3.getRange(3, 3, OCitems.length, 9).setValues([OCitems]); // paste operation, NumRows set equal to length of array

=========================

EDIT#1: Worked on improving performance using getValues of several cells instead of doing individual getValue() several times over. Unfortunately, this hasn't reduced the execution time in a stable or noticeable manner (sometimes it finished before 6min, sometimes not).

Posting code below (you can access it in script file "TestArrayMultiple2" in new Sheet shared below):

Using Execution transcript, I see that although the execution time of the getValue() lines that were previously taking very long has basically been reduced to zero, other lines of code are now taking more time and killing the gain achieved from the batching other getValue().

There are still 4-5 "individual" getValue() on specific cells (much less than before), but I don't understand why they would take so long. So it seems even if I removed the remaining "individual" getValue(), if only one remained, it would take even longer.

Seems to me it has something to do with caching (and I'm sure I don't fully understand this concept), for the following reasons:
1) It is always the first getValue() in the loop which takes the longest.
2) I tried to go down a different route, by changing the code for the copy/paste operation which occurrs after all emails are sent (line 150 in "TestArrayMultiple2" script file). I basically try to create an array which gets fed with more data at every loop (append/push method) but doesn't paste within every loop - the idea is to paste all the data at the end, after finishing looping. I still don't have it right (this second script file is the last one, "TestArrayMultiple3"), but I can see the emails get fired off much faster.

Once again, your help would be much appreciated.

> // version with 1 getDataRange array which stores for supplier ID, name, email, MaxTableRow for PO email, email subject all from Dashboard sheet

function TestArrayMultiple2() {

  var ss = SpreadsheetApp.getActiveSpreadsheet ();
  var sheet = ss.getSheetByName("Email");
  var sheet1 = ss.getSheetByName("Pedido email");
  var sheet2 = ss.getSheetByName("Dashboard");
  var sheet3 = ss.getSheetByName("AsignRec");
  var sheet4 = ss.getSheetByName("ListadoProductos");
  var sheet5 = ss.getSheetByName("Registro-Consolid");
  var sheet6 = ss.getSheetByName("Registro-Unico");

  var x = ss.getSheetByName("Dashboard").getRange("C4").getValue();
  Logger.log("x = " + x)

  var offsetV = 4; // number of rows of offset for email status to be inserted in Dashboard sheet

  var OffSetColProv = 1; // column in Dashboard sheet with supplier name
  var OffsetColMaxPOrows = 3; // Number of unique SKUs or rows in PO. Replace MaxTableRow formula in Email Sheet
  var OffSetColPzas = 4; // column in Dashboard sheet with number of items in supplier purchase order.
  var OffSetColEmail = 5; // column in Dashboard sheet with supplier email
  var OffSetColCC = 13; // column in Dashboard sheet with supplier email CC
  var OffSetColSubject = 14; // column in Dashboard sheet with supplier email Subject

  var colStatus = 11; // column in Dashboard sheet where send status of email inserted -----> LEAVE AS IS FOR NOW, not an offset, is fixed, col. K = 11
  var OffsetEmailRows = 8 // number of rows in Email sheet before the items in PO are shown

  var ProvNumEmail = sheet.getRange(1,2); // Supplier number in email sheet used to refresh products in purchase order email via FILTER formula

  var StatusRange = sheet2.getRange("K5:K100");
  Logger.log("StatusRange = " + StatusRange)

  var currentTime =  new Date();
  var timestamp = Utilities.formatDate(currentTime,'GMT-0600','dd/MM/yyyy HH:mm:ss');
  Logger.log("timestamp = " + timestamp);

  var ProvArray = sheet2.getRange("E5:S100");
  var DashValues = ProvArray.getValues();

  i = 0;

  do {

  var y = DashValues[i][0];
  Logger.log("y = " + y)

  ProvNumEmail.setValue(y);   // set value of next supplier in Email sheet to load next purchase order products

    // emails var here in order to update email value in IF email = ERROR condition and skip to else

  var Prov = DashValues[i][OffSetColProv];
  Logger.log("Prov = " + Prov);

  var EmailSubject = DashValues[i][OffSetColSubject];
  Logger.log("EmailSubject = " + EmailSubject)

  var MaxTableRow = DashValues[i][OffsetColMaxPOrows] + OffsetEmailRows;
  Logger.log("MaxTableRow = " + MaxTableRow)

  var EmailTo = DashValues[i][OffSetColEmail];
  Logger.log("EmailTo = " + EmailTo)

  var EmailCC = DashValues[i][OffSetColCC];
  Logger.log("EmailCC = " + EmailCC)

  var Piezas = DashValues[i][OffSetColPzas];
  Logger.log("Piezas = " + Piezas)

  SpreadsheetApp.flush();

  var name = "Petsy Compras - Juan Carlos León";
  var ReplyToEmail = "compras@petsy.mx";
  var email = EmailTo;
  var subject = EmailSubject;
  var name = name;
  var replyTo = ReplyToEmail;
  var Emailcc = EmailCC;
  var schedRange = sheet.getRange("B7:J"+MaxTableRow);
  var body = '
';
    body += "Estimados," +'
' + '
';
    body += "Envío la orden de compra, por un total de " + '' + Piezas + " piezas." + '' +'
' + '
';
    body += "Favor de confirmar las existencias lo más rápidamente posible, dentro del mismo correo y"+ ''+ " enviar factura a: "+ '' + "facturasproveedores@petsy.mx." +'
' + '
';
    body += "Al dar " +' '+ "RESPONDER A TODOS" + '' +" la tabla con los productos pedidos se hace editable: favor de marcar por cada item si será faltante." +'
' + '
';
    body += "Cualquier duda avísenme por favor." +'
' + '
';
    body += "Un saludo" +'
' + '
';
    body += ''     + "Juan Carlos León" + '' + '
';
    body += "Petsy Compras"+'
';
    body += "Mapa aquí: "+'
';
    body += "Fijo directo 1: (55) 68 12 07 97 / Fijo directo 2: (55) 68 12 07 99 / Cel y Whatsapp: 55 32 23 57 17"+'
' + '
';
    body += "" +'
' + '
';
    body += getHtmlTable(schedRange);
    body += '
';

  // variables for error email

  var emailERR = 'oscialom@petsy.mx'
  var subjectERR = 'ERROR ENVIO OC' + ' // ' + Prov + ' ' + timestamp

  if(email == 'ERROR' || MaxTableRow == 0) // skip condition to go begin loop with y+1

{

// if above skip condition is true, y+1 to move to next purchase order

  Logger.log("y = " + y);
  Logger.log("IF");
  sheet2.getRange(y + offsetV,colStatus).setValue('NOT_SENT'); // set email send status next to supplier in Dashboard sheet
  {
     GmailApp.sendEmail(emailERR, subjectERR, "Requires HTML",
                {
                    'name':name,
                    'replyTo':replyTo,
                    'htmlBody':'',
                    'cc':''});
        }

  i++;

  Logger.log("new i IF =" + 1);
  continue

}
else
{

  // if skip condition is false, fire current supplier purchase order email email

  Logger.log("i = " + i);
  Logger.log("y = " + y);
  Logger.log("ELSE");

  GmailApp.sendEmail(email, subject, "Requires HTML",
                {
                    'name':name,
                    'replyTo':replyTo,
                    'htmlBody':body,
                    'cc':EmailCC});
        }

sheet2.getRange(y + offsetV,colStatus).setValue('OK'); // set email send status next to supplier in Dashboard sheet

// START copy-paste Asign-Rec

var MaxTableRowASIGN = sheet3.getRange("A1").getValue();
Logger.log("MaxTableRowASIGN = " + MaxTableRowASIGN)

/// Get Range we want to change to creating Javascript array and paste at end only

  debugger; // stop debugger at this point !! REMOVE OR PLACE AT CORRECT LINE IF USING DEBUGGER

var OcNoHeader = sheet.getRange("B9:J" + MaxTableRow);
var ConsolAsignRec = sheet3.getRange("B3:K" + MaxTableRow);
var ProvOC = sheet.getRange("B2").getValue();
Logger.log("ProvOC = " + ProvOC)

var MaxRowB = sheet3.getRange("C1").getValue() + 1;
Logger.log("MaxRowB = " + MaxRowB);

var NextRowB = MaxRowB + 1;
Logger.log("NextRowB = " + NextRowB);

OcNoHeader.copyTo(sheet3.getRange(MaxTableRowASIGN + 1,3),{contentsOnly:true});
var NumRowsProv = OcNoHeader.getNumRows();

var ProvOCcolumn = sheet3.getRange(MaxRowB, 2, NumRowsProv)
Logger.log("ProvOCcolumn = " + ProvOCcolumn);

ProvOCcolumn.setValue(ProvOC);

// END copy-paste Asign-Rec

i++; // after firing email, y+1 to go to next supplier
Logger.log("i++ IF =" + 1);

Logger.log("new i ELSE =" + 1)

} // only do while x = max number of suppliers reached
  while (y<x);

  // set y = 1 to reset value again after finishing loop

  sheet.getRange(1,2).setValue(1); // reset ProvNumber = 1 to start again next time script is fired.

  var EmailsSent = sheet2.getRange("C10").getValue(); // set values
  Logger.log("EmailsSent = " + EmailsSent)

  var EmailErrors = sheet2.getRange("C11").getValue();
  Logger.log("EmailErrors = " + EmailErrors)

  var MaxTableRowEND = sheet2.getRange("C9").getValue();
  var schedRange = sheet2.getRange("E4:K" + MaxTableRowEND);
  var emailEND = "oscialom@petsy.mx";
  var subjectEND = 'OCs Inbound enviadas' + ' ' + timestamp + " (errores " +  EmailErrors + " / enviados " + EmailsSent + ")";
  var EmailCCEND = "";
  var bodyEND = getHtmlTable(schedRange);

   GmailApp.sendEmail(emailEND, subjectEND, "Requires HTML",
                {
                    'name':name,
                    'replyTo':replyTo,
                    'htmlBody':bodyEND,
                    'cc':EmailCCEND});

StatusRange.clearContent();

/// START RecordTimestamp code

  var Avals = sheet4.getRange("A1:A").getValues();
  var lastrow1 = Avals.filter(String).length;
  Logger.log('lastrow1 =' + lastrow1)

  var Avals2 = sheet5.getRange("A1:A").getValues();
  var lastrow2 = Avals2.filter(String).length;
  Logger.log('lastrow2 =' + lastrow2)

    sheet4.getRange("B2:B" + lastrow1).copyTo(sheet5.getRange(lastrow2 + 1, 1)) // copy order-items to Registro sheet, after last filled row

    sheet4.getRange("K2:K" + lastrow1).copyTo(sheet5.getRange(lastrow2 + 1, 2)) // copy Prov1 to Registro sheet, after last filled row

  var Avals3 = sheet5.getRange("C1:C").getValues();
  var lastrow2c = Avals3.filter(String).length;
  Logger.log('lastrow2c =' + lastrow2c);

  if(lastrow2 == 1)
  { sheet5.getRange(lastrow2c + 1, 3, lastrow1 - 1).setValue(timestamp)
    Logger.log('IF')

    }

    else
    {
    sheet5.getRange(lastrow2c + 1, 3, lastrow1 - 1).setValue(timestamp)
    Logger.log('ELSE')
    }

var MaxTableRowEMAIL = sheet6.getRange("G5").getValue()

var subject = "Items pedidos en OC automatizada " + timestamp
var email = "oscialom@petsy.mx";
var EmailCC = "";
var EmailBCC;
var name = "Petsy Compras";
var ReplyToEmail = "compras@petsy.mx"
var schedRange = sheet6.getRange("A1:C" + MaxTableRowEMAIL);
var body = getHtmlTable(schedRange);

{
     GmailApp.sendEmail(email, subject, "Requires HTML",
                {
                    'name':name,
                    'replyTo':ReplyToEmail,
                    'htmlBody':body,
                    'cc':''});
        }

/// END RecordTimestamp code

Logger.log("MaxTableRowASIGN " + MaxTableRowASIGN);

var endtime = new Date();
Logger.log("timestamp end " + timestamp);
Logger.log("endtime " + Utilities.formatDate(endtime,'GMT-0600','dd/MM/yyyy HH:mm:ss'));

var scripttime = (endtime - currentTime);
Logger.log("scripttime original" + scripttime);

// strip the ms
scripttime /= 1000;
Logger.log("scripttime / 1000" + scripttime);

// get seconds (Original had 'round' which incorrectly counts 0:28, 0:29, 1:30 ... 1:59, 1:0)
var seconds = Math.round(scripttime % 60);
Logger.log("scripttime % 60" + scripttime);

// remove seconds from the date
scripttime = Math.floor(scripttime / 60);
Logger.log("scripttime / 60" + scripttime);

// Browser.msgBox("Script completado en " + seconds + " segundos",Browser.Buttons.OK_CANCEL); // removed MsgBox to measure real execution time
Logger.log("seconds " + seconds)

}

=====================

ORIGINAL POST

I wrote a Google script to automate the purchase order process to several suppliers. The process takes a list of products (from sheet ListaProductos), formats the product info into an email format (sheet "Email"), sends the emails, and does some copy/pasting into other sheets of the same spreadsheet. However, I always run into the execution time at around 75% of the script. I'm fairly new to this, have been reading up but frankly don't know what to try next.

Body:
I see the problem in this part of code:

do {
  // read info from the sheet
  range.getValue();
  // more code here...

} // only do while x = max number of suppliers reached
  while (y<x)

Operation getValue takes much time to run. Best practice is to use the whole range:

var data = sheet.getDataRange().getValuses();

and then use data as source for further calculations.

See more info here:

https://developers.google.com/apps-script/best_practices


问:
Making a function constructor function in Javascript
How, if possible, do I create a function constructor function?..a constructor that also has prototype methods.

I know how to create an object constructor function i.e.

```<code>Function Thing(val) { this.prop1 = val  }
Thing.prototype.action = function()...
</code>```

But to make create a new function with prototype prop and methods, the best I can come up with is, for example:

```<code>Function Func(val) {
   var func = function(x) {return val*x};
   func.val = val;
   func.__proto__ = proto;
   return func;
}

const proto = {
   product: function(x) { return this.val*x },
};
</code>```

For the sake of code hygiene, is there a more elegant solution?

答:
try...</p>

```<code>function Person(name) {
  this.name = name;
}
// create a new instance
var person = new Person('codechimp');
console.log('person.constructor is ' + person.constructor);
</code>```

Body:
How, if possible, do I create a function constructor function?..a constructor that also has prototype methods.

I know how to create an object constructor function i.e.

Function Thing(val) { this.prop1 = val  }
Thing.prototype.action = function()...

But to make create a new function with prototype prop and methods, the best I can come up with is, for example:

Function Func(val) {
   var func = function(x) {return val*x};
   func.val = val;
   func.__proto__ = proto;
   return func;
}

const proto = {
   product: function(x) { return this.val*x },
};

For the sake of code hygiene, is there a more elegant solution?

Body:
try...

function Person(name) {
  this.name = name;
}
// create a new instance
var person = new Person('codechimp');
console.log('person.constructor is ' + person.constructor);


问:
How to insert a record in Sqlite?
please anybody tell me how to insert records in sqlite through objective c?</p>

答:
You can use a block of code like this

```<code>-(NSString*) GetDatabasePath {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
        NSUserDomainMask, YES) ;
    NSString *documentsDirectory = [paths objectAtIndex:0] ;
    return [documentsDirectory stringByAppendingPathComponent:@"Your Database"] ;
}

-(void)InsertPurchase {
        sqlite3_stmt *statement=nil;
        NSString *path = [self GetDatabasePath];
        NSString *query;

        if(sqlite3_open([path UTF8String],&db) == SQLITE_OK)
        {
            query = [NSString stringWithFormat: @"Your insert query"];

            if(sqlite3_prepare_v2(db, [query UTF8String], -1, &statement, NULL)
                        == SQLITE_OK)
            {
                sqlite3_step(statement);
            }
            sqlite3_finalize(statement);
        }
        sqlite3_close(db);
}
</code>```

This can be your interface

```<code>@interface Database : NSObject {
    sqlite3 *db;
}
</code>```

Title: How to insert a record in Sqlite?

Body:
You can use a block of code like this

-(NSString*) GetDatabasePath {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
        NSUserDomainMask, YES) ;
    NSString *documentsDirectory = [paths objectAtIndex:0] ;
    return [documentsDirectory stringByAppendingPathComponent:@"Your Database"] ;
}

-(void)InsertPurchase {
        sqlite3_stmt *statement=nil;
        NSString *path = [self GetDatabasePath];
        NSString *query;

        if(sqlite3_open([path UTF8String],&db) == SQLITE_OK)
        {
            query = [NSString stringWithFormat: @"Your insert query"];

            if(sqlite3_prepare_v2(db, [query UTF8String], -1, &statement, NULL)
                        == SQLITE_OK)
            {
                sqlite3_step(statement);
            }
            sqlite3_finalize(statement);
        }
        sqlite3_close(db);
}

This can be your interface

@interface Database : NSObject {
    sqlite3 *db;
}


问:
Printing records with condition Crystal reports
I am using stored procedure in mssql as backend, vb.net as frontend (just info).

There are a lot of records in the database and I am printing in crystal reports.

Now I want to filter the records from crystal report and not by adding a new parameter to procedure or changing database structure or else.

For now,Say there are columns : Name , Amount.

I want to put filter in amount like only display records whose amount above 100 or something. So other records with less than 100 should not be displayed.

This filter will be passed by the user so it'll be random.

I can't find a proper answer on internet. Might be a duplicate question, if so please post the link of the question if it is duplicated.!

Thanx anyways...!

答:
In general the idea is to:

Create the parameter (user choose what will be the input/value) - link

Set filters, what values should be displayed in regards to parameter - link

On right side there is a DataExplorer window, where You need to add a Parameter (define his name, what question will be shown to user and what type the param will be / what values can be set inside).

Once done, You can jump to Data tab of a report, click Interactive Filter and specify which column must fit what condition with what value = Parameter (that one user will enter in Report).

Example: I will create AmountParam, with message "What should be the minimum amount?". Type will be set to Integer. Going to Report->Data->Interactive Filter, choose Amount as a Column, AmountParam as a Parameter and set condition Greater then (>).


问:
how to create a list in R from two vectors (one would be the keys, the other the values)?
I have two vectors and I want to create a list in R where one vector are the keys and the other the values. I thought that I was going to find easily the answer in my books or googleing around and I was expecting to find a solution like when adding names to a vector ( names(v)<- names_vector), but I failed.

I have come myself with two possible solutions but none of them seems elegant to me. R is not my main programming language but I assume that being R so pragmatic a better solution should exist (something like list(keys=x, values=y)).

My solution 1: the classical loop solution:

```<code>    > xx <- 1:3
    > yy <- letters1:3
    > zz =list()
    >for(i in 1:length(yy)) {zz[[yy[i]]]<-xx[i]}
</code>```

my solution 2: indirect path through named vectors:

```<code>    > names(xx) <- letters[1:3]
    > as.list(xx)
</code>```

Seems that I have a solution, but my vectors have 1 million or more elements  and I am worried not only about coding style (important to me) but also about efficiency (but I don't know how to do profiling in R). Is there a more appropriate way of doing this? Is it a good practice to use the named vector shortcut?

[[UPDATE]] my applogies, probably I oversimplify the question to make it reproducible. I wanted to give names to the elements of a list. I tried names() first but seems that I did something wrong and did not work. So I got the wrong idea that names() does not work with lists. But they indeed do as shown by the accepted answer

答:
Hong's output is wrong.

Should use vals[["key42"]]

```<code>> vals[["key42"]]
[1] 42

vals <- 1:1000000
keys <- paste0("key", 1:1000000)
names(vals) <- keys

vals["key42"]
key42
   42
</code>```

Body:
I have two vectors and I want to create a list in R where one vector are the keys and the other the values. I thought that I was going to find easily the answer in my books or googleing around and I was expecting to find a solution like when adding names to a vector ( names(v)<- names_vector), but I failed.

I have come myself with two possible solutions but none of them seems elegant to me. R is not my main programming language but I assume that being R so pragmatic a better solution should exist (something like list(keys=x, values=y)).

My solution 1: the classical loop solution:

    > xx <- 1:3
    > yy <- letters1:3
    > zz =list()
    >for(i in 1:length(yy)) {zz[[yy[i]]]<-xx[i]}

my solution 2: indirect path through named vectors:

    > names(xx) <- letters[1:3]
    > as.list(xx)

Seems that I have a solution, but my vectors have 1 million or more elements  and I am worried not only about coding style (important to me) but also about efficiency (but I don't know how to do profiling in R). Is there a more appropriate way of doing this? Is it a good practice to use the named vector shortcut?

[[UPDATE]] my applogies, probably I oversimplify the question to make it reproducible. I wanted to give names to the elements of a list. I tried names() first but seems that I did something wrong and did not work. So I got the wrong idea that names() does not work with lists. But they indeed do as shown by the accepted answer

Body:
Hong's output is wrong.

Should use vals[["key42"]]

> vals[["key42"]]
[1] 42

vals <- 1:1000000
keys <- paste0("key", 1:1000000)
names(vals) <- keys

vals["key42"]
key42
   42


问:
Rotate text with flying saucer to pdf
I´m using flying saucer and itext to convert html to pdf, in the order to write text in vertical orientation, i try the simple css:

```<code>style="writing-mode: tb-rl";
</code>```

the transform rotations for browsers:

```<code>transform: rotate(270deg)!important;
-ms-transform:rotate(270deg); /* IE 9 */
-moz-transform:rotate(270deg); /* Firefox */
-webkit-transform:rotate(270deg); /* Safari and Chrome */
-o-transform:rotate(270deg); /* Opera */
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand', M11=0.7071067811865476, M12=-0.7071067811865475, M21=0.7071067811865475, M22=0.7071067811865476); /* IE6,IE7 */
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(SizingMethod='auto expand', M11=0.7071067811865476, M12=-0.7071067811865475, M21=0.7071067811865475, M22=0.7071067811865476)"; /* IE8 */
</code>```

But with no success... :(

Same one know how to rotate the html text, with flying saucer and itext?

Thanks in advance :)

答:
I've been doing some digging around. From the FlyingSaucer User forums, it seems like the transform property is not supported yet. However it should be easier to implement as it does not affect layout.

If you are not interested in digging into source, you can implement a replaced element to take in the data, convert to SVG and use it in your layout. Here are few examples of similar usage for barcode. http://andreas.haufler.info/2012/12/generating-barcodes-in-pdfs-with-flying.html

There is another code example here - Using Flying Saucer to Render Images to PDF In Memory

Using browser-engine backed libraries like PhantomJS might not be ideal when your entire application is in Java.

Title: Rotate text with flying saucer to pdf

Body:
I´m using flying saucer and itext to convert html to pdf, in the order to write text in vertical orientation, i try the simple css:

style="writing-mode: tb-rl";

the transform rotations for browsers:

transform: rotate(270deg)!important;
-ms-transform:rotate(270deg); /* IE 9 */
-moz-transform:rotate(270deg); /* Firefox */
-webkit-transform:rotate(270deg); /* Safari and Chrome */
-o-transform:rotate(270deg); /* Opera */
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand', M11=0.7071067811865476, M12=-0.7071067811865475, M21=0.7071067811865475, M22=0.7071067811865476); /* IE6,IE7 */
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(SizingMethod='auto expand', M11=0.7071067811865476, M12=-0.7071067811865475, M21=0.7071067811865475, M22=0.7071067811865476)"; /* IE8 */

But with no success... :(

Same one know how to rotate the html text, with flying saucer and itext?

Thanks in advance :)


问:
Reason to take more loading time of asp.net page and how to reduce it
I have the following queries regarding the loading time of asp.net page.
Anyone can help.
What are the possibilities of asp.net page consuming more loading time?.
How to reduce the loading time of asp.net web page?</p>

答:
If you are selecting data from a database on startup, I would pay attention not to:

Select not needed data from the database doing stuff like

```<code>SELECT * from TabelX
</code>```

I would specify exactly what columns to use

Don't load all the data in a list at the beginning, but load id only when you need it. More than this, I would load like only 20-50-100 rows, only those that can be shown on the page at a time.

If you are joining large number of rows, I would consider creating views.

Body:
If you are selecting data from a database on startup, I would pay attention not to:

Select not needed data from the database doing stuff like

SELECT * from TabelX

I would specify exactly what columns to use

Don't load all the data in a list at the beginning, but load id only when you need it. More than this, I would load like only 20-50-100 rows, only those that can be shown on the page at a time.

If you are joining large number of rows, I would consider creating views.


问:
How do I import a new code style scheme to IntelliJ IDEA for JavaScript or other languages?
When I view JavaScript code in IntelliJ Community it isn't formatted or coloured in any way

and when I look at the languages listed under Settings|Editor|Code Style I'm missing JavaScript from the list of supported languages but i've definitely seen it in this list before.

How can I import JavaScript or other languages in so I can make it look better.

答: I think that you are using Community Edition of Intellij IDEA which is not supporting JavaScript as can be seen here, thus the solution is to update to Ultimate, then your JavaScript code will be highlighted.


问:
How can I get the data-id attribute?
I'm using the jQuery Quicksand plugin. I need to get the data-id of the clicked item and pass it to a webservice.

How do I get the data-id attribute? I'm using the .on() method to re-bind the click event for sorted items.

$("#list li").on('click', function() {
  //  ret = DetailsView.GetProject($(this).attr("#data-id"), OnComplete, OnTimeOut, OnError);
  alert($(this).attr("#data-id"));
});```
<pre class="snippet-code-html lang-html prettyprint-override"><code><script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>

<ul id="list" class="grid">
  <li data-id="id-40" class="win">

      <img src="themes/clean/images/win.jpg" class="project-image" alt="get data-id" />

  </li>
</ul></code>```

答:
Accessing the data attribute with its own id is a bit easy for me.

```<code>$("#Id").data("attribute");
</code>```

function myFunction(){
  alert($("#button1").data("sample-id"));
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<button type="button" id="button1" data-sample-id="gotcha!" onclick="myFunction()"> Clickhere </button></code>```

Title: How can I get the data-id attribute?

Body:
Accessing the data attribute with its own id is a bit easy for me.

$("#Id").data("attribute");

function myFunction(){
  alert($("#button1").data("sample-id"));
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<button type="button" id="button1" data-sample-id="gotcha!" onclick="myFunction()"> Clickhere </button>


问:
How to access data from ajax call after the ajax call ends
I am making a ajax calls that returns me some data from the server. I work on string function on the data that come from ajax call. From my knowledge i can see the string operation begins before the ajax call gets over. Often giving me undefined error. Here is my ajax call

```<code> $.ajax({

        type: "POST",
        url: "/add_director",
        headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
        data: formData,
        cache: false,
        contentType: false,
        processData: false,
        success: function(data) {
            $('#addDirModal').modal('hide');
            insertDirector(data);
        },
        error : function(xhr ,status ,error)
        {
            console.log(xhr);
            alert(xhr);
        }
    });
</code>```

Here is my insertDirector function

```<code>function insertDirector(data){
      console.log(data);
      if (data.msg == "1") {
        $.each(data,function(key,value){
            var dir_name = value.dir_name;
            var dir_pan = value.dir_pan;
            var dir_din = value.dir_din;
            var dir_addr = value.dir_addr;
            var dir_id = value.id;
            var dir_img = value.dir_img;

              if (dir_name.val().length > 15) {
                var dir_r_name = dir_name.substr(0,15);
              }

              else{
                var dir_r_name = dir_name;
              }
         });
        }
       }
</code>```

Here when i work on substr() it throws the error Cannot read property 'val' of undefined. I can see this is because the substr() is executed before the ajax request is completed. how do i fix this ?

EDITED

Here is the response

```<code>{"msg":"1","director":{"dir_name":"Naveen","dir_pan":"AAAAA1111B","dir_din":"123456","dir_addr":"dsadasdasdasdsadasdas","dir_img":"1490852438.jpg","user_id":3,"updated_at":"2017-03-30 05:40:38","created_at":"2017-03-30 05:40:38","id":15}}
</code>```

答:
try this way :</p>

```<code>function insertDirector(data) {
    console.log(data);
    if (data.msg == "1") {

        var dir_name = data.director.dir_name;
        var dir_pan = data.director.dir_pan;
        var dir_din = data.director.dir_din;
        var dir_addr = data.director.dir_addr;
        var dir_id = data.director.id;
        var dir_img = data.director.dir_img;

        if (dir_name.length > 15) {
            var dir_r_name = dir_name.substr(0, 15);
        }

        else {
            var dir_r_name = dir_name;
        }

    }
}
</code>```

Body:
I am making a ajax calls that returns me some data from the server. I work on string function on the data that come from ajax call. From my knowledge i can see the string operation begins before the ajax call gets over. Often giving me undefined error. Here is my ajax call

 $.ajax({

        type: "POST",
        url: "/add_director",
        headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
        data: formData,
        cache: false,
        contentType: false,
        processData: false,
        success: function(data) {
            $('#addDirModal').modal('hide');
            insertDirector(data);
        },
        error : function(xhr ,status ,error)
        {
            console.log(xhr);
            alert(xhr);
        }
    });

Here is my insertDirector function

function insertDirector(data){
      console.log(data);
      if (data.msg == "1") {
        $.each(data,function(key,value){
            var dir_name = value.dir_name;
            var dir_pan = value.dir_pan;
            var dir_din = value.dir_din;
            var dir_addr = value.dir_addr;
            var dir_id = value.id;
            var dir_img = value.dir_img;

              if (dir_name.val().length > 15) {
                var dir_r_name = dir_name.substr(0,15);
              }

              else{
                var dir_r_name = dir_name;
              }
         });
        }
       }

Here when i work on substr() it throws the error Cannot read property 'val' of undefined. I can see this is because the substr() is executed before the ajax request is completed. how do i fix this ?

EDITED

Here is the response

{"msg":"1","director":{"dir_name":"Naveen","dir_pan":"AAAAA1111B","dir_din":"123456","dir_addr":"dsadasdasdasdsadasdas","dir_img":"1490852438.jpg","user_id":3,"updated_at":"2017-03-30 05:40:38","created_at":"2017-03-30 05:40:38","id":15}}

Body:
try this way :

function insertDirector(data) {
    console.log(data);
    if (data.msg == "1") {

        var dir_name = data.director.dir_name;
        var dir_pan = data.director.dir_pan;
        var dir_din = data.director.dir_din;
        var dir_addr = data.director.dir_addr;
        var dir_id = data.director.id;
        var dir_img = data.director.dir_img;

        if (dir_name.length > 15) {
            var dir_r_name = dir_name.substr(0, 15);
        }

        else {
            var dir_r_name = dir_name;
        }

    }
}


问:
app-debug.apk is crashing while I install it manually on my Android device
My app is running fine on Android device when I run project from Android studio. But when I install app-debug.apk manually on my device then app is crashing on starting. And app-debug-unaligned.apk is not generating.
Kindly give any solution, Thanks in advance.  </p>

答: Delete debug.apk  from output folder under build in app.  and generate again and install .