问:
Calling JQuery Button Clicks/Form Submit in Firebase Functions and Hosting
I am trying to make a website using Firebase Functions and Hosting Feature. Everything works perfectly but for some reason when the user tries to fill the form, the website reloads. I am trying to place an onClick Listener on the button in the form or attach the onSubmit to the form. But nothing gets called. I don't know what I am doing wrong. Any help will be appreciated.</p>

```<code><form id="join-us-form" class="container" onsubmit="joinUsButtonCalled()">
                        <div class="form-row">
                            <div class="form-group col-sm-12">
                                <label for="joinUsFullName" class="sr-only">Full Name</label>
                                <div class="input-group mb-2 mb-sm-0" style="border: 1px solid white; border-radius: 5px">
                                    <div class="input-group-addon" style="background-color: transparent">
                                        <i class="fal fa-user" style="color: white;"></i>
                                    </div>
                                    <input type="text" class="form-control" id="joinUsFullName" placeholder="Your Name"
                                           required style="background: transparent; color: white">
                                    <div class="invalid-feedback">
                                        Please provide us with your name.
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="form-row">
                            <div class="form-group col-sm-12">
                                <label for="joinUsEmailAddress" class="sr-only">Email Address</label>
                                <div class="input-group mb-2 mb-sm-0" style="border: 1px solid white; border-radius: 5px">
                                    <div class="input-group-addon" style="background-color: transparent">
                                        <i class="fal fa-envelope" style="color: white;"></i>
                                    </div>
                                    <input type="email" class="form-control" id="joinUsEmailAddress"
                                           placeholder="Email Address"
                                           required style="background: transparent; color: white">
                                    <div class="invalid-feedback">
                                        Please provide a valid email.
                                    </div>
                                </div>
                            </div>
                        </div>

                        <div class="form-row">
                            <div class="form-group col-sm-12">
                                <label for="joinUsWorkAs" class="sr-only">Work as..</label>
                                <div class="input-group mb-2 mb-sm-0" style="border: 1px solid white; border-radius: 5px">
                                    <div class="input-group-addon" style="background-color: transparent">
                                        <i class="fal fa-tasks" style="color: white;"></i>
                                    </div>
                                    <input type="text" class="form-control" id="joinUsWorkAs"
                                           placeholder="e.g: Designer, App Developer ..."
                                           required style="background: transparent; color: white">
                                    <div class="invalid-feedback">
                                        Please provide a valid work as.
                                    </div>
                                </div>
                            </div>
                        </div>

                        <button id="joinUsButton" class="btn btn-warning btn-rounded" type="submit" onClick="joinUsButtonCalled()">Get in Touch</button>
                    </form>

<script>
    function joinUsButtonCalled(event){
        $('#join-us-form').preventDefault();
        console.log('I am being called here in Join Us ()');
        event.preventDefault();
    }
</script>
</code>```

答:
Since you are using JQUERY I would try something like this:

```<code>$('#join-us-form').submit(function(ev) {
    ev.preventDefault(); //to stop the form from submitting
    //do your validation stuff
    this.submit(); // If all the validations succeeded
});

$('#joinUsButton').on('click', function(ev){
     ev.preventDefault(); //to stop the form from submitting
     //do your validation stuff
     $('#join-us-form').submit();// If all the validations succeeded
});
</code>```

The problem with your script was that "event" was actually "undefined" cause "onSubmit" doesn't pass any argument to the function "joinUsButtonCalled".

Same for "$('#join-us-form').preventDefault();" cause preventDefault() is not a method of a generic JQUERY object, it belong to the EventObject, like the ones fired by a user click.
I guess your console was full of "undefined" error.
Finally you can get rid of the "onSumbit" and "onClick" attribute:

```<code><form id="join-us-form" class="container">
...
    <button id="joinUsButton" class="btn btn-warning btn-rounded" type="submit">Get in Touch</button>
</form>
</code>```

Body:
I am trying to make a website using Firebase Functions and Hosting Feature. Everything works perfectly but for some reason when the user tries to fill the form, the website reloads. I am trying to place an onClick Listener on the button in the form or attach the onSubmit to the form. But nothing gets called. I don't know what I am doing wrong. Any help will be appreciated.

<form id="join-us-form" class="container" onsubmit="joinUsButtonCalled()">

                                Full Name

                                    <input type="text" class="form-control" id="joinUsFullName" placeholder="Your Name"
                                           required style="background: transparent; color: white">

                                        Please provide us with your name.

                                Email Address

                                    <input type="email" class="form-control" id="joinUsEmailAddress"
                                           placeholder="Email Address"
                                           required style="background: transparent; color: white">

                                        Please provide a valid email.

                                Work as..

                                    <input type="text" class="form-control" id="joinUsWorkAs"
                                           placeholder="e.g: Designer, App Developer ..."
                                           required style="background: transparent; color: white">

                                        Please provide a valid work as.

                        <button id="joinUsButton" class="btn btn-warning btn-rounded" type="submit" onClick="joinUsButtonCalled()">Get in Touch</button>
                    </form>

Body:
Since you are using JQUERY I would try something like this:

$('#join-us-form').submit(function(ev) {
    ev.preventDefault(); //to stop the form from submitting
    //do your validation stuff
    this.submit(); // If all the validations succeeded
});

$('#joinUsButton').on('click', function(ev){
     ev.preventDefault(); //to stop the form from submitting
     //do your validation stuff
     $('#join-us-form').submit();// If all the validations succeeded
});

The problem with your script was that "event" was actually "undefined" cause "onSubmit" doesn't pass any argument to the function "joinUsButtonCalled".

Same for "$('#join-us-form').preventDefault();" cause preventDefault() is not a method of a generic JQUERY object, it belong to the EventObject, like the ones fired by a user click.
I guess your console was full of "undefined" error.
Finally you can get rid of the "onSumbit" and "onClick" attribute:

<form id="join-us-form" class="container">
...
    <button id="joinUsButton" class="btn btn-warning btn-rounded" type="submit">Get in Touch</button>
</form>


来源: stackexchange

问:
How to detect if React Material UI Select Field is expanded?
I am trying to determine if SelectField is expanded or not, i.e. if the dropdown and it's MenuItems are visible.

Currently I use roughly following approach:

```<code><SelectField onClick={() => this.setState({ isExpanded: true })} >
    <MenuItem primaryText={
      <MenuItemContent onHide={() => this.setState({ isExpanded: false })}} />
    }>
</SelectField>
</code>```

and in MenuItemContent I implement

```<code>class MenuItemContent extends React.Component {
  componentWillUnmount = () => this.props.onHide()
}
</code>```

This approach has a drawback, that when you click outside the menu, the componentWillUnmount call is not triggered immidiately, but cca after 200ms, despite the MenuItems are no longer visible.

The Select field menu can be expanded by clicking it, and when is expanded, it will hide either when some menu item is clicked, or user clicks outside the menu.

This is how the SelectField looks when is expanded:

And here is collapsed:

答:
For the better handling of SelectField close event you can use property dropDownMenuProps:

```<code>/**
 * Object that can handle and override any property of component DropDownMenu.
 */
dropDownMenuProps: PropTypes.object,
</code>```

By using this prop we can pass to DropDownMenu component onClose prop with handler function, which will be fired instantly after DropDownMenu close (caused by ESC, outside click or item select). Unfortunately DropDownMenu component dont provide similar prop to determine the opening so the only way (without
extending the component) is to follow your approach with onClick event handler.
Here is my working test example:

```<code>  onSelectClose = () => {
    console.log("close")
  }

  onSelectOpen = () => {
    console.log("open")
  }

  render() {
    return (
      <MuiThemeProvider>
        <div className="App">
          <SelectField
            floatingLabelText="Frequency"
            onClick={this.onSelectOpen}
            dropDownMenuProps={{
              onClose: this.onSelectClose
            }}
            value={this.state.value}
            onChange={this.handleChange}>
              <MenuItem value={1} primaryText="Never" />
              <MenuItem value={2} primaryText="Every Night" />
              <MenuItem value={3} primaryText="Weeknights" />
              <MenuItem value={4} primaryText="Weekends" />
              <MenuItem value={5} primaryText="Weekly" />
          </SelectField>
        </div>
      </MuiThemeProvider>
    );
  }
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I am trying to determine if SelectField is expanded or not, i.e. if the dropdown and it's MenuItems are visible.

Currently I use roughly following approach:

<SelectField onClick={() => this.setState({ isExpanded: true })} >
    <MenuItem primaryText={
      <MenuItemContent onHide={() => this.setState({ isExpanded: false })}} />
    }>
</SelectField>

and in MenuItemContent I implement

class MenuItemContent extends React.Component {
  componentWillUnmount = () => this.props.onHide()
}

This approach has a drawback, that when you click outside the menu, the componentWillUnmount call is not triggered immidiately, but cca after 200ms, despite the MenuItems are no longer visible.

The Select field menu can be expanded by clicking it, and when is expanded, it will hide either when some menu item is clicked, or user clicks outside the menu.

This is how the SelectField looks when is expanded:

And here is collapsed:

Body:
For the better handling of SelectField close event you can use property dropDownMenuProps:

/**
 * Object that can handle and override any property of component DropDownMenu.
 */
dropDownMenuProps: PropTypes.object,

By using this prop we can pass to DropDownMenu component onClose prop with handler function, which will be fired instantly after DropDownMenu close (caused by ESC, outside click or item select). Unfortunately DropDownMenu component dont provide similar prop to determine the opening so the only way (without
extending the component) is to follow your approach with onClick event handler.
Here is my working test example:

  onSelectClose = () => {
    console.log("close")
  }

  onSelectOpen = () => {
    console.log("open")
  }

  render() {
    return (
      <MuiThemeProvider>
        <div className="App">
          <SelectField
            floatingLabelText="Frequency"
            onClick={this.onSelectOpen}
            dropDownMenuProps={{
              onClose: this.onSelectClose
            }}
            value={this.state.value}
            onChange={this.handleChange}>
              <MenuItem value={1} primaryText="Never" />
              <MenuItem value={2} primaryText="Every Night" />
              <MenuItem value={3} primaryText="Weeknights" />
              <MenuItem value={4} primaryText="Weekends" />
              <MenuItem value={5} primaryText="Weekly" />
          </SelectField>
        </div>
      </MuiThemeProvider>
    );
  }


问:
Is Partial Index a good Idea for a boolean column that is almost all false?
I have a table: Parent that has many Children (other table where every child row has a parent_id).

So I had the DB index for children table on parent_id. Which worked well, since I was fetching a specific parent's children all the time..

Now I introduced the :disabled boolean column on children table.
And most times I will fetch only the enabled children (disabled = false).

Is it smart to add a partial index like this, since this is the query I'm using the most?

CREATE INDEX index_for_parent_and_enabled ON children USING btree (parent_id, disabled) WHERE (disabled = false)

Or since there are very few disabled children, is it better to keep the index only on the parent_id column?

Obs: I'm using postgres

I'd really appreciate any comments on this. :)

答:
If you have a foreign key on child(parent_id), it is advisable to have an index on the column so that operations on the parent table don't have to scan the complete child table.

If you usually query for

```<code>... WHERE parent_id = $1 AND NOT disabled
</code>```

and only few records are NOT disabled, it could be good to have an additional index

```<code>CREATE INDEX ON child (parent_id) WHERE NOT disabled;
</code>```

It does not make any sense to have disabled in the index, since the condition is already in the WHERE expression. That would only inflate the index.

Body:
If you have a foreign key on child(parent_id), it is advisable to have an index on the column so that operations on the parent table don't have to scan the complete child table.

If you usually query for

... WHERE parent_id = $1 AND NOT disabled

and only few records are NOT disabled, it could be good to have an additional index

CREATE INDEX ON child (parent_id) WHERE NOT disabled;

It does not make any sense to have disabled in the index, since the condition is already in the WHERE expression. That would only inflate the index.


问:
Excel VBA - Evaluate Function Returning #NAME? Error
So I wrote a VBA code to calculate the number of blanks, non-blanks and total entries under each header for some input data. I want to add a code that copies and pastes the values from one sheet to another, dedupes the values, gives me the unique list of values under each header, number of unique values, and the number of times those unique values are occurring under the header.

Blanks: I used the countblank function earlier, but it would skip certain empty fields, so I changed it to sumproduct(len(Range)=0)*1).
Non-Blanks: I wrote a similar function and tried to calculate the above.

It turns out VBA is unable to process the Sumproduct function. Here are the approaches I have tried:

```<code> 1. Application.WorksheetFunction.Sumproduct(...)
 2. ..Number.. = "=Sumproduct(...)"
 3. ..Number.. = Evaluate("Sumproduct(...)")
 4. ..Number.. = Worksheet.Evaluate("Sumproduct(...)")
</code>```

Below is the code for the macro, I am writing the code on the Input_File, i.e., the Input worksheet.

```<code>Sub Dedupe()
ThisWorkbook.Worksheets("Control_Totals").Cells.ClearContents

Dim lRow As Long
Dim lCol As Long
Dim i As Long
Dim j As Long
Dim Input_File As Worksheet
Dim Output_File As Worksheet
Dim Dedup_File As Worksheet
Dim Col_Let As String
Dim Rng As String
Dim blank As String
Dim non_blank As String

Set Input_File = ThisWorkbook.Worksheets("Input")
Set Output_File = ThisWorkbook.Worksheets("Control_Totals")
Set Dedup_File = ThisWorkbook.Worksheets("Deduped")

With Output_File
        .Cells(1, 1) = "Field_Name"
        .Cells(1, 2) = "Blanks"
        .Cells(1, 3) = "Non-Blanks"
        .Cells(1, 4) = "Total"
End With

'Finding the last row among all entries, including the blank ones
lRow = Input_File.Cells.Find(What:="*", _
                    After:=Range("A1"), _
                    LookAt:=xlPart, _
                    LookIn:=xlFormulas, _
                    SearchOrder:=xlByRows, _
                    SearchDirection:=xlPrevious, _
                    MatchCase:=False).Row

MsgBox "Last Row: " & lRow

'Finding the last column header/field
lCol = Input_File.Cells.Find(What:="*", _
                  LookAt:=xlPart, _
                  LookIn:=xlFormulas, _
                  SearchOrder:=xlByColumns, _
                  SearchDirection:=xlPrevious, _
                  MatchCase:=False).Column

MsgBox "Last Column: " & lCol

i = 1

'Finding the number of blank and non-blank entries for all the fields
Do While i < lCol + 1
Col_Let = ColumnLetter(i)
Rng = "Input!" & "Col_Let" & "2" & ":" & "lRow"

    Output_File.Cells(i + 1, 1) = Input_File.Cells(1, i)

         blank = "SumProduct((Len(Rng) = 0) * 1)"
         non_blank = "SumProduct((Len(Rng) > 0) * 1)"

    Output_File.Cells(i + 1, 2).Value = Evaluate(blank)
    Output_File.Cells(i + 1, 3).Value = Evaluate(non_blank)
    Output_File.Cells(i + 1, 4) = lRow - 1

    'Deduping the data under the headers
    j = 0
    For j = 1 To lRow
    Dedup_File.Cells(j, i).Value = Input_File.Cells(j, i).Value
    j = j + 1
    Next
    Dedup_File.Range(Cells(1, i), Cells(lRow, i)).RemoveDuplicates Columns:=1, _
    Header:=xlYes

        i = i + 1

Loop

End Sub
</code>```

答:
These lines don't do what you think they do

```<code>Col_Let = ColumnLetter(i)
Rng = "Input!" & "Col_Let" & "2" & ":" & "lRow"
</code>```

Rng is always a string containing "Input!Col_Let2:lRow"

What you meant was: (I think)
        Rng = "Input!" & Col_Let & "2" & ":" & Col_Let & lRow

Secondly Rng exists only within this vba routine - it doesn't mean anything to Excel so you can't use it in an Excel Formula. You need

```<code>blank = "SumProduct((Len(" & Rng.address & ") = 0) * 1)"
</code>```

and finally SumProduct doesn't like those sort of tricks in VBA (It relies on excel expanding the 1 into an array automatically). A better solution:

```<code>Dim cBlank as long
Dim cNonBlank as long
Dim r as range
For each r in rng
if r.text = "" then
   cBlank= cBlank+1
else
   cNonBlank = cNonBlank +1
 end if
 next r
</code>```

Body:
So I wrote a VBA code to calculate the number of blanks, non-blanks and total entries under each header for some input data. I want to add a code that copies and pastes the values from one sheet to another, dedupes the values, gives me the unique list of values under each header, number of unique values, and the number of times those unique values are occurring under the header.

Blanks: I used the countblank function earlier, but it would skip certain empty fields, so I changed it to sumproduct(len(Range)=0)*1).
Non-Blanks: I wrote a similar function and tried to calculate the above.

It turns out VBA is unable to process the Sumproduct function. Here are the approaches I have tried:

 1. Application.WorksheetFunction.Sumproduct(...)
 2. ..Number.. = "=Sumproduct(...)"
 3. ..Number.. = Evaluate("Sumproduct(...)")
 4. ..Number.. = Worksheet.Evaluate("Sumproduct(...)")

Below is the code for the macro, I am writing the code on the Input_File, i.e., the Input worksheet.

Sub Dedupe()
ThisWorkbook.Worksheets("Control_Totals").Cells.ClearContents

Dim lRow As Long
Dim lCol As Long
Dim i As Long
Dim j As Long
Dim Input_File As Worksheet
Dim Output_File As Worksheet
Dim Dedup_File As Worksheet
Dim Col_Let As String
Dim Rng As String
Dim blank As String
Dim non_blank As String

Set Input_File = ThisWorkbook.Worksheets("Input")
Set Output_File = ThisWorkbook.Worksheets("Control_Totals")
Set Dedup_File = ThisWorkbook.Worksheets("Deduped")

With Output_File
        .Cells(1, 1) = "Field_Name"
        .Cells(1, 2) = "Blanks"
        .Cells(1, 3) = "Non-Blanks"
        .Cells(1, 4) = "Total"
End With

'Finding the last row among all entries, including the blank ones
lRow = Input_File.Cells.Find(What:="*", _
                    After:=Range("A1"), _
                    LookAt:=xlPart, _
                    LookIn:=xlFormulas, _
                    SearchOrder:=xlByRows, _
                    SearchDirection:=xlPrevious, _
                    MatchCase:=False).Row

MsgBox "Last Row: " & lRow

'Finding the last column header/field
lCol = Input_File.Cells.Find(What:="*", _
                  LookAt:=xlPart, _
                  LookIn:=xlFormulas, _
                  SearchOrder:=xlByColumns, _
                  SearchDirection:=xlPrevious, _
                  MatchCase:=False).Column

MsgBox "Last Column: " & lCol

i = 1

'Finding the number of blank and non-blank entries for all the fields
Do While i < lCol + 1
Col_Let = ColumnLetter(i)
Rng = "Input!" & "Col_Let" & "2" & ":" & "lRow"

    Output_File.Cells(i + 1, 1) = Input_File.Cells(1, i)

         blank = "SumProduct((Len(Rng) = 0) * 1)"
         non_blank = "SumProduct((Len(Rng) > 0) * 1)"

    Output_File.Cells(i + 1, 2).Value = Evaluate(blank)
    Output_File.Cells(i + 1, 3).Value = Evaluate(non_blank)
    Output_File.Cells(i + 1, 4) = lRow - 1

    'Deduping the data under the headers
    j = 0
    For j = 1 To lRow
    Dedup_File.Cells(j, i).Value = Input_File.Cells(j, i).Value
    j = j + 1
    Next
    Dedup_File.Range(Cells(1, i), Cells(lRow, i)).RemoveDuplicates Columns:=1, _
    Header:=xlYes

        i = i + 1

Loop

End Sub

Body:
These lines don't do what you think they do

Col_Let = ColumnLetter(i)
Rng = "Input!" & "Col_Let" & "2" & ":" & "lRow"

Rng is always a string containing "Input!Col_Let2:lRow"

What you meant was: (I think)
        Rng = "Input!" & Col_Let & "2" & ":" & Col_Let & lRow

Secondly Rng exists only within this vba routine - it doesn't mean anything to Excel so you can't use it in an Excel Formula. You need

blank = "SumProduct((Len(" & Rng.address & ") = 0) * 1)"

and finally SumProduct doesn't like those sort of tricks in VBA (It relies on excel expanding the 1 into an array automatically). A better solution:

Dim cBlank as long
Dim cNonBlank as long
Dim r as range
For each r in rng
if r.text = "" then
   cBlank= cBlank+1
else
   cNonBlank = cNonBlank +1
 end if
 next r


问:
Split a large character column with different amount of values into multiple columns
I have a character column with a different amount of values per row. This is just a small example:

```<code>GoodForMeal %>% head(5)
# A tibble: 5 x 1
GoodForMeal
<chr>
1 dessert': False, 'latenight': False, 'lunch': True, 'dinner': True
2 dessert': False, 'latenight': False, 'lunch': True, 'dinner': True
3 <NA>
4 dessert': False, 'latenight': False, 'lunch': True, 'dinner': True
5 dessert': False, 'latenight': False, 'lunch': True, 'dinner': True
</code>```

Here is a dput() of the first row of the column:

```<code>structure(list(GoodForMeal = "dessert': False, 'latenight': False, 'lunch': True, 'dinner': True, 'breakfast': False, 'brunch': False}"), .Names = "GoodForMeal", row.names = c(NA,
-1L), class = c("tbl_df", "tbl", "data.frame"))
</code>```

I want to assign the values before the colon as column names and the values after the colon as the values of the respective column.

Example:

```<code>   desert latenight lunch diner
1  False  False     True  True
2  False  False     True  True
3  NA     NA        NA    NA
4  False  False     True  True
5  False  False     True  True
</code>```

I tried it with the tidyr packadge and the separate and the spread function:

```<code>separate(GoodForMeal, c("key", "value"), sep = ":", extra = "merge") %>% spread(key, value)
</code>```

The problem is the r is not splitting all the values before the colon but just the first value.

So the result looks like this:

```<code>GoodForMeal %>% str()

Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   4464 obs. of  2 variables:
 $ dessert': chr  " False, 'latenight': False, 'lunch': True, 'dinner': False, 'breakfast': False, 'brunch': False}" " False, 'latenight': False, 'lunch': True, 'dinner': True, 'breakfast': False, 'brunch': False}" " False, 'latenight': False, 'lunch': False, 'dinner': False, 'breakfast': False, 'brunch': False}" " False, 'latenight': False, 'lunch': True, 'dinner': True, 'breakfast': False, 'brunch': False}" ...
 $ <NA>    : chr  NA NA NA NA ...
</code>```

Any Idea how to split the values so that it´s looking like in the example? THX

答:
Working with the test data you've provided, I would use mutate first to rid the column of characters such ' and :, along with the meal time keywords. This allows you to split on the comma that separates the various meal times. The following is an illustration:

```<code>df <- structure(list(GoodForMeal = "dessert': False, 'latenight': False, 'lunch': True, 'dinner': True, 'breakfast': False, 'brunch': False}"),
                .Names = "GoodForMeal", row.names = c(NA, -1L),
                class = c("tbl_df", "tbl", "data.frame"))

df %>%
  mutate(GoodForMeal = trimws(gsub("[':]|dessert|lunch|dinner|latenight|brunch",
                                   "",
                                   GoodForMeal))) %>%
  separate(GoodForMeal,
           c("dessert", "latenight", "lunch", "dinner"),
           ", ",
           extra="drop")
</code>```

It should yield:

```<code># A tibble: 1 x 4
# dessert latenight lunch dinner
# * <chr>     <chr> <chr>  <chr>
#   False     False  True   True
</code>```

I hope this proves useful.

Body:
I have a character column with a different amount of values per row. This is just a small example:

GoodForMeal %>% head(5)
# A tibble: 5 x 1
GoodForMeal
<chr>
1 dessert': False, 'latenight': False, 'lunch': True, 'dinner': True
2 dessert': False, 'latenight': False, 'lunch': True, 'dinner': True
3 <NA>
4 dessert': False, 'latenight': False, 'lunch': True, 'dinner': True
5 dessert': False, 'latenight': False, 'lunch': True, 'dinner': True

Here is a dput() of the first row of the column:

structure(list(GoodForMeal = "dessert': False, 'latenight': False, 'lunch': True, 'dinner': True, 'breakfast': False, 'brunch': False}"), .Names = "GoodForMeal", row.names = c(NA,
-1L), class = c("tbl_df", "tbl", "data.frame"))

I want to assign the values before the colon as column names and the values after the colon as the values of the respective column.

Example:

   desert latenight lunch diner
1  False  False     True  True
2  False  False     True  True
3  NA     NA        NA    NA
4  False  False     True  True
5  False  False     True  True

I tried it with the tidyr packadge and the separate and the spread function:

separate(GoodForMeal, c("key", "value"), sep = ":", extra = "merge") %>% spread(key, value)

The problem is the r is not splitting all the values before the colon but just the first value.

So the result looks like this:

GoodForMeal %>% str()

Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   4464 obs. of  2 variables:
 $ dessert': chr  " False, 'latenight': False, 'lunch': True, 'dinner': False, 'breakfast': False, 'brunch': False}" " False, 'latenight': False, 'lunch': True, 'dinner': True, 'breakfast': False, 'brunch': False}" " False, 'latenight': False, 'lunch': False, 'dinner': False, 'breakfast': False, 'brunch': False}" " False, 'latenight': False, 'lunch': True, 'dinner': True, 'breakfast': False, 'brunch': False}" ...
 $ <NA>    : chr  NA NA NA NA ...

Any Idea how to split the values so that it´s looking like in the example? THX

Body:
Working with the test data you've provided, I would use mutate first to rid the column of characters such ' and :, along with the meal time keywords. This allows you to split on the comma that separates the various meal times. The following is an illustration:

df <- structure(list(GoodForMeal = "dessert': False, 'latenight': False, 'lunch': True, 'dinner': True, 'breakfast': False, 'brunch': False}"),
                .Names = "GoodForMeal", row.names = c(NA, -1L),
                class = c("tbl_df", "tbl", "data.frame"))

df %>%
  mutate(GoodForMeal = trimws(gsub("[':]|dessert|lunch|dinner|latenight|brunch",
                                   "",
                                   GoodForMeal))) %>%
  separate(GoodForMeal,
           c("dessert", "latenight", "lunch", "dinner"),
           ", ",
           extra="drop")

It should yield:

# A tibble: 1 x 4
# dessert latenight lunch dinner
# * <chr>     <chr> <chr>  <chr>
#   False     False  True   True

I hope this proves useful.


问:
How many arguments takes the foldr function of Haskell?
I am new to Haskell and I am reading the book  "Real World Haskell". In the Chapter 4 of the book the author asks as an exercise to rewrite the groupBy function using fold. One of the readers of the book (Octavian Voicu ) gave the following solution:

```<code>
theCoolGroupBy :: (a -> a -> Bool) -> [a] -> [[a]]
theCoolGroupBy eq xs = tail $ foldr step (\_ -> [[]]) xs $ (\_ -> False)
                       where step x acc = \p -> if p x then rest p else []:rest (eq x)
                                          where rest q = let y:ys = acc q in (x:y):ys
</code>```

My question is simple: I know that foldr takes 3 arguments: a function, an initial value and a list. But in the second line of the code foldr takes 4 arguments. Why this happens?
Thank you.

答:
In this situation, I think it is best to look at the type signature of foldr:

```<code>foldr :: (a -> b -> b) -> b -> [a] -> b
</code>```

and to match that to the expression we have (with added parenthesis for clarity):

```<code>(foldr step (\_ -> [[]]) xs) (\_ -> False)
</code>```

The second argument of foldr is the same type as its result. In this case the second argument is a function. In this case, this means that the foldr expression with 3 arguments will be a function.

What you see to be the 4th argument of the foldr function could also be thought of as the 1st argument of the foldr result!

Body:
I am new to Haskell and I am reading the book  "Real World Haskell". In the Chapter 4 of the book the author asks as an exercise to rewrite the groupBy function using fold. One of the readers of the book (Octavian Voicu ) gave the following solution:

theCoolGroupBy :: (a -> a -> Bool) -> [a] -> [[a]]
theCoolGroupBy eq xs = tail $ foldr step (\_ -> [[]]) xs $ (\_ -> False)
                       where step x acc = \p -> if p x then rest p else []:rest (eq x)
                                          where rest q = let y:ys = acc q in (x:y):ys

My question is simple: I know that foldr takes 3 arguments: a function, an initial value and a list. But in the second line of the code foldr takes 4 arguments. Why this happens?
Thank you.

Body:
In this situation, I think it is best to look at the type signature of foldr:

foldr :: (a -> b -> b) -> b -> [a] -> b

and to match that to the expression we have (with added parenthesis for clarity):

(foldr step (\_ -> [[]]) xs) (\_ -> False)

The second argument of foldr is the same type as its result. In this case the second argument is a function. In this case, this means that the foldr expression with 3 arguments will be a function.

What you see to be the 4th argument of the foldr function could also be thought of as the 1st argument of the foldr result!

ContentLicense: CC BY-SA 2.5


问:
C# / MigraDoc: Long table breaking across pages, top and bottom border
I have a long table in C#, MigraDoc, which splits across two pages.
I need only outer borders.
When the table is split, the top border and the bottom border will not be visible.
Is there a way to make them visible?
(It cannot be determined where the page break will be.)</p>

答:
For top border you could use the row.HeadingFormat = true and then set the top border on it like this:

```<code>var table = new Table();
var headingRow = table.AddRow();
headingRow.HeadingFormat = true;
headingRow.Borders.Top.Width = 1;
// your other table content here
</code>```

I'm currently looking into how to do the same thing for the bottom table border, but it seems that there's no way to do it.

Body:
For top border you could use the row.HeadingFormat = true and then set the top border on it like this:

var table = new Table();
var headingRow = table.AddRow();
headingRow.HeadingFormat = true;
headingRow.Borders.Top.Width = 1;
// your other table content here

I'm currently looking into how to do the same thing for the bottom table border, but it seems that there's no way to do it.


问:
Converting {integer} to f32 in Rust
I want to convert a value from {integer} to f32:

```<code>struct Vector3 {
    pub x: f32,
    pub y: f32,
    pub z: f32,
}

for x in -5..5 {
    for y in -5..5 {
        for z in -5..5 {
            let foo: Vector3 = Vector3 { x: x, y: y, z: z };
            // do stuff with foo
        }
    }
}
</code>```

The compiler chokes on this with a type mismatch error (expecting f32 but getting {integer}). Unfortunately I can not simply change Vector3. I'm feeding a C-API with this.

Is there any easy and concise way I can convert x, y and z from {integer} to f32?

I guess there is no builtin conversion from i32 or {integer} to f32 because it could be lossy in certain situations. However, in my case the range I'm using is so small that this wouldn't be an issue. So I would like to tell the compiler to convert the value anyways.

Interestingly, the following works:

```<code>for x in -5..5 {
    let tmp: i32 = x;
    let foo: f32 = tmp as f32;
}
</code>```

I'm using a lot more that just one foo and one x so this turns hideous really fast.

Also, this works:

```<code>for x in -5i32..5i32 {
    let foo: f32 = x as f32;
    // do stuff with foo here
}
</code>```

But with my usecase this turns into:

```<code>for x in -5i32..5i32 {
    for y in -5i32..5i32 {
        for z in -5i32..5i32 {
            let foo: Vector3 = Vector3 {
                x: x as f32,
                y: y as f32,
                z: z as f32,
            };
            // do stuff with foo
        }
    }
}
</code>```

Which I think is pretty unreadable and an unreasonable amount of cruft for a simple conversion.

What am I missing here?

答:
The only integer types available are i8, i16, i32, etc. and their unsigned equivalents. There is no such type as {integer}. This is just a placeholder emitted by the compiler before it has determined the actual type by inference from the whole-method context.

The problem is that, at the point where you call Vector3 {x: x as f32, y: y as f32, z: z as f32}, it doesn't yet know exactly what x, y and z are, and therefore doesn't know what operations are available. It could use the operations given to determine the type, if it was a bit more intelligent; see bug report for details.

There is a conversion from i32 to f32, so you should be able to do this:

```<code>let foo = Vector3 {x: (x as i32) as f32, y: (y as i32) as f32, z: (z as i32) as f32};
</code>```

Title: Converting {integer} to f32 in Rust

Body:
I want to convert a value from {integer} to f32:

struct Vector3 {
    pub x: f32,
    pub y: f32,
    pub z: f32,
}

for x in -5..5 {
    for y in -5..5 {
        for z in -5..5 {
            let foo: Vector3 = Vector3 { x: x, y: y, z: z };
            // do stuff with foo
        }
    }
}

The compiler chokes on this with a type mismatch error (expecting f32 but getting {integer}). Unfortunately I can not simply change Vector3. I'm feeding a C-API with this.

Is there any easy and concise way I can convert x, y and z from {integer} to f32?

I guess there is no builtin conversion from i32 or {integer} to f32 because it could be lossy in certain situations. However, in my case the range I'm using is so small that this wouldn't be an issue. So I would like to tell the compiler to convert the value anyways.

Interestingly, the following works:

for x in -5..5 {
    let tmp: i32 = x;
    let foo: f32 = tmp as f32;
}

I'm using a lot more that just one foo and one x so this turns hideous really fast.

Also, this works:

for x in -5i32..5i32 {
    let foo: f32 = x as f32;
    // do stuff with foo here
}

But with my usecase this turns into:

for x in -5i32..5i32 {
    for y in -5i32..5i32 {
        for z in -5i32..5i32 {
            let foo: Vector3 = Vector3 {
                x: x as f32,
                y: y as f32,
                z: z as f32,
            };
            // do stuff with foo
        }
    }
}

Which I think is pretty unreadable and an unreasonable amount of cruft for a simple conversion.

What am I missing here?

Body:
The only integer types available are i8, i16, i32, etc. and their unsigned equivalents. There is no such type as {integer}. This is just a placeholder emitted by the compiler before it has determined the actual type by inference from the whole-method context.

The problem is that, at the point where you call Vector3 {x: x as f32, y: y as f32, z: z as f32}, it doesn't yet know exactly what x, y and z are, and therefore doesn't know what operations are available. It could use the operations given to determine the type, if it was a bit more intelligent; see bug report for details.

There is a conversion from i32 to f32, so you should be able to do this:

let foo = Vector3 {x: (x as i32) as f32, y: (y as i32) as f32, z: (z as i32) as f32};


问:
CKEDITOR : Select text using start , end index position
How do I select Particular text using text index position?

I have a para in editor and I just try to select select an Text using their index position's how can I do this?

Sample

```<code><p>My Tes<b>ti</b>ng Point</p>
</code>```

I wanted to select Testing using their index positions 4 and 11 .
And I'm using the below code to achieve this.But it isn't Working at all.

```<code>    var editor = CKEDITOR.instances.editor1;
    range = editor.createRange();
    range.setStart(4);
    range.setEnd(11);
    editor.getSelection().selectRanges([range]);
</code>```

Please, anyone help me.

Note:

If I'm using Text node concept then the text shouldn't be selected.

答:
Keep in mind that CKEditor content is HTML data which is not flat, but has more like tree structure so it is not possible to simply set selection using only indexes.

As you can see in the docs for range.setStart and range.setEnd it requires two parameters startNode/endNode and startOffset/endOffset. The offset is always set relatively to specific element, not absolute to the beginning of the content.

In your case, you should first find specific elements and then set offset relatively to those elements:

```<code>var editable = editor.editable(),
    startNode = editable.findOne( 'p' ),
    endNode = startNode,
    range = editor.createRange();

range.setStart( startNode.getChild( 0 ), 4 ); // Get first child which is text node "My Tes".
range.setEnd( endNode.getChild( 2 ), 2 ); // Get third child which is text node "ng Point".
editor.getSelection().selectRanges( [ range ] );
</code>```

Body:
How do I select Particular text using text index position?

I have a para in editor and I just try to select select an Text using their index position's how can I do this?

Sample

My Testing Point

I wanted to select Testing using their index positions 4 and 11 .
And I'm using the below code to achieve this.But it isn't Working at all.

    var editor = CKEDITOR.instances.editor1;
    range = editor.createRange();
    range.setStart(4);
    range.setEnd(11);
    editor.getSelection().selectRanges([range]);

Please, anyone help me.

Note:

If I'm using Text node concept then the text shouldn't be selected.

Body:
Keep in mind that CKEditor content is HTML data which is not flat, but has more like tree structure so it is not possible to simply set selection using only indexes.

As you can see in the docs for range.setStart and range.setEnd it requires two parameters startNode/endNode and startOffset/endOffset. The offset is always set relatively to specific element, not absolute to the beginning of the content.

In your case, you should first find specific elements and then set offset relatively to those elements:

var editable = editor.editable(),
    startNode = editable.findOne( 'p' ),
    endNode = startNode,
    range = editor.createRange();

range.setStart( startNode.getChild( 0 ), 4 ); // Get first child which is text node "My Tes".
range.setEnd( endNode.getChild( 2 ), 2 ); // Get third child which is text node "ng Point".
editor.getSelection().selectRanges( [ range ] );


问:
Field Validator Fires undesirably
I have a page with the following mark up

```<code><%@ Page Title="" Language="C#" MasterPageFile="~/CaseAdmin.master" AutoEventWireup="true" CodeBehind="AddExhibit.aspx.cs" Inherits="Prototype5.AddExhibit" %>
</code>```

```<code>    <h2 class="style2">
    <strong><span style="color: #FFFFFF">Add Exhibit
    Form</span></strong></h2>
<div style="width: 600px">
<table style="width: 303px" align="left">
        <tr>
            <td class="style26" style="background-color: #666666">
                <p class="style5" style="color: #000000; background-color: #666666;">
                    <strong style="background-color: #666666">Select Existing Case ID:
                </strong>
                </p></td>
            <td class="" style="background-color: #C0C0C0" align="left">
                <asp:DropDownList ID="DropDownListcaseid" runat="server"
                    onselectedindexchanged="DropDownListcaseid_SelectedIndexChanged">
                </asp:DropDownList>
                <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
                    ControlToValidate="DropDownListcaseid"
                    ErrorMessage="Please select a valid case id from the dropdown menu"
                    ForeColor="Red">*</asp:RequiredFieldValidator>
            </td>
        </tr>
        <tr>
            <td class="style4" colspan="2">
                 </td>
        </tr>
    </table>

    <asp:SqlDataSource ID="SqlDataSource1" runat="server"
        ConnectionString="<%$ ConnectionStrings:CMSSQL3ConnectionString1 %>"
        SelectCommand="SELECT [CaseID] FROM [Cases]"></asp:SqlDataSource>

</div>
<div style="width: 603px; height: 75px; ">

    <table style="height: 66px; width: 598px; top: 277px; left: 268px;"
        align="left">
        <tr>
            <td class="bold"
                style="color: #000000; background-color: #666666; width: 127px;">
                <strong>Exhibit Type</strong></td>
            <td class="bold" style="background-color: #666666; width: 228px;">
                <span style="color: #000000">Exhibit Image</td>
            <td class="bold" style="background-color: #666666; width: 111px;">
                <span style="color: #000000">Stored Location</span></td>
            <td class="bold" style="background-color: #666666; color: #000000;">
                Officer ID</span></td>
        </tr>
        <tr>
            <td class="style32" style="background-color: #C0C0C0; width: 127px;">
                <asp:DropDownList ID="exhibitTypeDropDownList" runat="server">
                    <asp:ListItem></asp:ListItem>
                    <asp:ListItem>Hard Disk</asp:ListItem>
                    <asp:ListItem>Pen Drive</asp:ListItem>
                    <asp:ListItem>Laptop</asp:ListItem>
                    <asp:ListItem>Palm Devce</asp:ListItem>
                    <asp:ListItem>Mobile Phone</asp:ListItem>
                    <asp:ListItem>Tablet PC</asp:ListItem>
                    <asp:ListItem>Pager</asp:ListItem>
                </asp:DropDownList>
                <asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server"
                    ControlToValidate="exhibitTypeDropDownList"
                    ErrorMessage="Please Enter the type of exhibit. eg. Harddisk"
                    ForeColor="Red" ondisposed="addExhibitButton_Click">*</asp:RequiredFieldValidator>
            </td>
            <td class="style28" style="background-color: #C0C0C0; width: 228px;">
                <asp:FileUpload ID="exhibitImageFileUpload" runat="server" />
            </td>
            <td class="style20" style="background-color: #C0C0C0; width: 111px;">
                <asp:DropDownList ID="storedLocationDropDownList" runat="server">
                    <asp:ListItem></asp:ListItem>
                    <asp:ListItem>B-15/4</asp:ListItem>
                    <asp:ListItem>B-10/1</asp:ListItem>
                    <asp:ListItem>B-5/4</asp:ListItem>
                </asp:DropDownList>
                <asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server"
                    ControlToValidate="storedLocationDropDownList"
                    ErrorMessage="Please enter a valid stored location" ForeColor="Red"
                    ondisposed="addExhibitButton_Click">*</asp:RequiredFieldValidator>
            </td>
            <td class="style30" style="background-color: #C0C0C0">
                <asp:DropDownList ID="DropDownList1" runat="server"
                    DataSourceID="officersSqlDataSource" DataTextField="PoliceID"
                    DataValueField="PoliceID" Width="79px" Height="26px">
                </asp:DropDownList>
                <asp:RequiredFieldValidator ID="RequiredFieldValidator4" runat="server"
                    ControlToValidate="DropDownList1"
                    ErrorMessage="Please select a valid Officer id from the dropdown list"
                    ForeColor="Red" ondisposed="addExhibitButton_Click">*</asp:RequiredFieldValidator>
            </td>
        </tr>
    </table>

</div>
<div style="width: 609px; height: 23px;">
                </div>
<div style="margin-top:12px; width: 232px; text-align:left; font-size:1.3em;">

    <asp:SqlDataSource ID="officersSqlDataSource"
        runat="server"
        ConnectionString="<%$ ConnectionStrings:CMSSQL3ConnectionString1 %>"
        SelectCommand="SELECT PoliceID FROM PoliceOfficers"></asp:SqlDataSource>
    <table align="left">
        <tr>
            <td align="center">
                <asp:ValidationSummary ID="ValidationSummary1" runat="server" ForeColor="Red"
                    HeaderText="The following errors occured." />
            </td>
        </tr>
    </table>

    </div>
    <div style="margin-top:12px; width: 456px;">

        <table  style="width: 450px" align="left">
            <tr>
                <td align="center" colspan="3">
                    <asp:Label ID="messageLabel" runat="server" BackColor="White" ForeColor="Red"
                        Visible="False"></asp:Label>
                </td>
            </tr>
            <tr>
                <td align="center" style="width: 96px">
                    <asp:Button ID="cancelButton" runat="server" Text="Cancel"
                        onclick="cancelButton_Click" height="26px" width="101px" />
                </td>
                <td  style="width: 237px">
                     </td>
                <td align="center">
                    <asp:Button ID="addExhibitButton" runat="server" Text="Add Exhibit"
                        onclick="addExhibitButton_Click" />
                </td>
            </tr>
        </table>

    </div>
</code>```

and the following interface look

I wish to perform validation on the page only when the "add exhibit button" is clicked. so in my code behind, i used an "if(page.isvalid)" to check for page validation when the button is clicked. However any other button i click fires the validation as well... I presume its because every button click tries to load a page and that calls the validator to action. how do i allow work around the validation such that, only the " add exhibit button" triggers the page validation?

答:
You need to set the ValidationGroup property on the button and the validator. That way you can control what validation takes place.

The ValidationGroup property is an arbitrary tag that you can add to your validators and buttons to group them into logical units. So in your case, I would do this:

For your validators that are relevant for the add exhibit action.

```<code><asp:RequiredFieldValidator ID="RequiredFieldValidator4" ValidationGroup="AddExhibit" ...
</code>```

For your button that triggers your add exhibit.

```<code><asp:Button ID="addExhibitButton" ValidationGroup="AddExhibit"
</code>```

Title: Field Validator Fires undesirably

Body:
I have a page with the following mark up

<%@ Page Title="" Language="C#" MasterPageFile="~/CaseAdmin.master" AutoEventWireup="true" CodeBehind="AddExhibit.aspx.cs" Inherits="Prototype5.AddExhibit" %>

    Add Exhibit
    Form

                    Select Existing Case ID:

                <asp:DropDownList ID="DropDownListcaseid" runat="server"
                    onselectedindexchanged="DropDownListcaseid_SelectedIndexChanged">
                </asp:DropDownList>
                <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
                    ControlToValidate="DropDownListcaseid"
                    ErrorMessage="Please select a valid case id from the dropdown menu"
                    ForeColor="Red">*</asp:RequiredFieldValidator>

    <asp:SqlDataSource ID="SqlDataSource1" runat="server"
        ConnectionString="<%$ ConnectionStrings:CMSSQL3ConnectionString1 %>"
        SelectCommand="SELECT [CaseID] FROM [Cases]"></asp:SqlDataSource>

                Exhibit Type

                Exhibit Image

                Stored Location

                Officer ID

                <asp:DropDownList ID="exhibitTypeDropDownList" runat="server">
                    <asp:ListItem></asp:ListItem>
                    <asp:ListItem>Hard Disk</asp:ListItem>
                    <asp:ListItem>Pen Drive</asp:ListItem>
                    <asp:ListItem>Laptop</asp:ListItem>
                    <asp:ListItem>Palm Devce</asp:ListItem>
                    <asp:ListItem>Mobile Phone</asp:ListItem>
                    <asp:ListItem>Tablet PC</asp:ListItem>
                    <asp:ListItem>Pager</asp:ListItem>
                </asp:DropDownList>
                <asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server"
                    ControlToValidate="exhibitTypeDropDownList"
                    ErrorMessage="Please Enter the type of exhibit. eg. Harddisk"
                    ForeColor="Red" ondisposed="addExhibitButton_Click">*</asp:RequiredFieldValidator>

                <asp:FileUpload ID="exhibitImageFileUpload" runat="server" />

                <asp:DropDownList ID="storedLocationDropDownList" runat="server">
                    <asp:ListItem></asp:ListItem>
                    <asp:ListItem>B-15/4</asp:ListItem>
                    <asp:ListItem>B-10/1</asp:ListItem>
                    <asp:ListItem>B-5/4</asp:ListItem>
                </asp:DropDownList>
                <asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server"
                    ControlToValidate="storedLocationDropDownList"
                    ErrorMessage="Please enter a valid stored location" ForeColor="Red"
                    ondisposed="addExhibitButton_Click">*</asp:RequiredFieldValidator>

                <asp:DropDownList ID="DropDownList1" runat="server"
                    DataSourceID="officersSqlDataSource" DataTextField="PoliceID"
                    DataValueField="PoliceID" Width="79px" Height="26px">
                </asp:DropDownList>
                <asp:RequiredFieldValidator ID="RequiredFieldValidator4" runat="server"
                    ControlToValidate="DropDownList1"
                    ErrorMessage="Please select a valid Officer id from the dropdown list"
                    ForeColor="Red" ondisposed="addExhibitButton_Click">*</asp:RequiredFieldValidator>

    <asp:SqlDataSource ID="officersSqlDataSource"
        runat="server"
        ConnectionString="<%$ ConnectionStrings:CMSSQL3ConnectionString1 %>"
        SelectCommand="SELECT PoliceID FROM PoliceOfficers"></asp:SqlDataSource>

                <asp:ValidationSummary ID="ValidationSummary1" runat="server" ForeColor="Red"
                    HeaderText="The following errors occured." />

                    <asp:Label ID="messageLabel" runat="server" BackColor="White" ForeColor="Red"
                        Visible="False"></asp:Label>

                    <asp:Button ID="cancelButton" runat="server" Text="Cancel"
                        onclick="cancelButton_Click" height="26px" width="101px" />

                    <asp:Button ID="addExhibitButton" runat="server" Text="Add Exhibit"
                        onclick="addExhibitButton_Click" />

and the following interface look

I wish to perform validation on the page only when the "add exhibit button" is clicked. so in my code behind, i used an "if(page.isvalid)" to check for page validation when the button is clicked. However any other button i click fires the validation as well... I presume its because every button click tries to load a page and that calls the validator to action. how do i allow work around the validation such that, only the " add exhibit button" triggers the page validation?

Body:
You need to set the ValidationGroup property on the button and the validator. That way you can control what validation takes place.

The ValidationGroup property is an arbitrary tag that you can add to your validators and buttons to group them into logical units. So in your case, I would do this:

For your validators that are relevant for the add exhibit action.

<asp:RequiredFieldValidator ID="RequiredFieldValidator4" ValidationGroup="AddExhibit" ...

For your button that triggers your add exhibit.

<asp:Button ID="addExhibitButton" ValidationGroup="AddExhibit"


问:
Need help to create a JavsScript array that will store several squares in a straight line on top of a existing polygon using Google Map
I have a html file that I included here. The file has text boxes and one push button. The push button will be activated in JavaScript file.

When the JavaScript runs it has an initialization section that loads the Google Maps tool to do certain measurements of a location or roof.

I need to create a function that will do the followings:
The existing code is already creating a square area or polygon. So idea is to create few smaller squares those will fit into the existing square in a straight line with small spaces in between of the squares.

I have attached the JavaScript code and highlighted the section where this new function or code should evolve.

I just started learning JavaScript specially google map API and I am stuck. Please assist me how I can implement this, it will be monumental help.

JavaScript file

// JavaScript source code

'use strict';
var mapScript = (function () {

    var GMap; // global variable within the solar module scope
    var squarePolys = []; //global array of Shape that will be attached to google maps

    function initMap() {
        // Load map at default location
        GMap = new google.maps.Map(document.getElementById('map'), {
            center: { lat: 37.76963799867498, lng: -122.45126726263503 },
            mapTypeId: google.maps.MapTypeId.SATELLITE,
            draggableCursor: 'crosshair',
            zoom: 20,
            disableDefaultUI: true
        });

        // force orthorgraphic imagery
        GMap.setTilt(0);

        // wait till map display is fully updated before drawing an area or roof section
        google.maps.event.addListenerOnce(GMap, "projection_changed", makeASite);

        //Hook up the
        var createButton = $("#create-button");
        createButton.click(function () {
            makeASite();
        });
    }

    //creating an area with modules
    function makeASite() {
        deletePreviousSite(); //removed any old polgyons first

        // draw default area or roof rectangle
        var rAreaSqPoly = constructRFSqPoly();
        squarePolys.push(rAreaSqPoly);

        // Create unites
        var unites = makeUnits(rAreaSqPoly);
        for (var i = 0; i < unites.length; i++) {
            squarePolys.push(unites[i]);
        }

        render();
    }

    // Create the default roof or an area rectangle
    function constructRFSqPoly() {
        //  The areas rectangle definition.
        //  Center:   the latitude, longitude location of the center of the rectangle
        //  Width:    width of rectangel in meters
        //  Height:   height of rectangel
        //  rotation: rotation angle of rectangle
        var rAreaSqPolyChoices = {
            center: new google.maps.LatLng(37.76963799867498, -122.45126726263503),
            width: 40.46, // meters
            length: 28.35,
            rotation: 20, // degrees
            color: '#0072ff',
            googleMap: GMap
        };

        // Create a google Shape object to overlay on the aerial
        return new Shape(rAreaSqPolyChoices);
    }

    // Create a list of pv module rectangles those will be later attached to the map
    function makeUnits(rAreaSqPoly) {
        var unitSqPolys = [];

        var unitWd = Number($("#site-width").val());
        var unitLn = Number($("#site-length").val());
        var unitSp = Number($("#site-spacing").val());

        ****Here I want to draw unites (square/polygon) on top of an
        exiting polygon (this could be a car parking lot or roof). The
        square are a straight line with spaces in between****

        return unitSqPolys;
    }

    // Redraws each Shape in the Shape list
    function render() {
        for (var i = 0; i < squarePolys.length; i++) {
            var Shape = squarePolys[i];
            Shape.clearMap();
            Shape.attachToMap();
        }
    }

    //Removes old Shapes from map and clears out the Shape list
    function deletePreviousSite() {
        for (var i = 0; i < squarePolys.length; i++) {
            var Shape = squarePolys[i];
            Shape.clearMap();
        }
        squarePolys = [];
    }

    var Shape = (function () { //This is the class definition for Shape
        //Width and length are in distance units,
        //Center is a google maps point in lat,lng coordinates
        //Rotation is in degress
        function Shape(options)
         { //This is the constructor for thos class
            // if(width !== "number" || length !== "number" || center !== "object", rotation !== "number")
            // throw new Error("Invalid arguments for constructing a Shape object");
            var _self = this;
            _self.width = options.width;
            _self.length = options.length;
            _self.center = options.center;
            _self.rotation = options.rotation;
            _self.googleMap = options.googleMap;
            _self.color = typeof options.color === "string" ? options.color : "#0072ff";
            _self.line = [];

            createShape();
            // In JavaScript member functions declared inside the contruction are private
            function createShape() {
                // Create rectangle coordinates, in latitude, longitude space to define an area or roof section of rectangle
                var line = [
                    Shape.setValuesInMtr(_self.center, _self.length / 2, -1 * _self.width / 2),
                    Shape.setValuesInMtr(_self.center, -1 * _self.length / 2, -1 * _self.width / 2),
                    Shape.setValuesInMtr(_self.center, -1 * _self.length / 2, 1 * _self.width / 2),
                    Shape.setValuesInMtr(_self.center, _self.length / 2, _self.width / 2)
                ];

                // Rotate the coordinates by the angle relative to the center of it
                _self.line = moveline(line, _self.rotation, _self.center);

                _self.googleMapsShape = new google.maps.Shape({
                    lines: _self.line,
                    strokeColor: _self.color,
                    strokeOpacity: 0.8,
                    strokeWeight: 2,
                    fillColor: _self.color,
                    fillOpacity: 0.35
                });
            }

            // Rotates an input array of latitude, longitude locations by the specified
            // angle around the specified latitude/longitude center
            function moveline(line, angle, origin) {
                var thisProjection = _self.googleMap.getProjection();

                var originPt = thisProjection.fromLatLngToPoint(origin);

                var moveOrders = line.map(function (latLng) {
                    var point = thisProjection.fromLatLngToPoint(latLng);

                    var rotatedLatLng = thisProjection.fromPointToLatLng(circulatePts(point, originPt, angle));
                    return rotatedLatLng;
                });
                return moveOrders;
            };

            // Rotation transformation
            function circulatePts(point, origin, angle) {
                var thisAngleR = angle * Math.PI / 180.0;
                return {
                    x: Math.cos(thisAngleR) * (point.x - origin.x) - Math.sin(thisAngleR) * (point.y - origin.y) + origin.x,
                    y: Math.sin(thisAngleR) * (point.x - origin.x) + Math.cos(thisAngleR) * (point.y - origin.y) + origin.y
                };
            }
        }

        //Attaches Shape to google maps
        Shape.prototype.attachToMap = function () { //public member function
            this.googleMapsShape.setMap(this.googleMap);
        };

        //Removes this Shape from google maps
        Shape.prototype.clearMap = function () { //public member function
            this.googleMapsShape.setMap(null);
        };

        // When provide a latitude, longitude location, and a distance north as well as east,
        // will return a new latitude, longitude location by the distances.
        Shape.setValuesInMtr = function (pointLatLng, nhMeters, eTMeters)
        { //Public static member function

            var R = 6378137; //PlanetEarth’s radius, sphere

            //offsets in radians
            var dLat = nhMeters / R;
            var dLon = eTMeters / (R * Math.cos(Math.PI * pointLatLng.lat() / 180));

            return new google.maps.LatLng(
                pointLatLng.lat() + dLat * 180 / Math.PI,
                pointLatLng.lng() + dLon * 180 / Math.PI);
        };

        return Shape
    })();

    return {
        initMap: initMap
    }
})();```
<pre class="snippet-code-html lang-html prettyprint-override"><code><!DOCTYPE html>
<html>
<head>
    <title>Simple Map To Test</title>
    <meta name="viewport" content="initial-scale=1.0">
    <meta charset="utf-8">
    <style>
        html, body {
            height: 100%;
            margin: 0;
            padding: 0;
        }

        #map {
            height: 60%;
            width: 60%;
        }

        #site-input {
            margin: 10px;
        }

        input {
            margin: 5px;
        }

        button {
            margin: 5px;
        }
    </style>
</head>
<body>
    <div id="site-input">
        Wd: <input type="text" id="site-width" value="5"><br>
        Ln: <input type="text" id="site-length" value="7"><br>
        Sp: <input type="text" id="site-spacing" value="0"><br>
        <button id="create-button">Create</button><br>
    </div>

    <div id="map"></div>

    <script src="./mapScript.js"></script>

    <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=mapScript.initMap" async defer></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.3/jquery.min.js"></script>

</body>
</html></code>```

答:
Okay, try this.

This is not the final form.  Look what happens, tell me which input and buttons you need ...

I made it (pretty much) from scratch, because it's easier for me to concentrate on the problem and forget all the rest.
Bu you should definitly put it back in your code format, with var mapScript = (function () { ...

The main weapon is the geometry library, which you have to load :
maps.googleapis.com/maps/api/js?callback=initMap&libraries=geometry
(again, in your code this would be mapScript.initMap )

it gives you

computeOffset (you give a point A, a distance and a heading, it returns point B)

computeHeading (you give a point A and point B, it returns the heading)

computeDistanceBetween (you give a point A and point B, it returns the distance)

instructions:

you can fill in point A and point B (the heading input is calculated, it doesn't change anything, it just tells you the angle)

or

click on the map, first for point A.  Click again for point B.  Then the function is automatically loaded, it reads the spacing/rows/cols data and makes the grid.

index.htm

```<code><!DOCTYPE html>
<html>
<head>
<title>Simple Map To Test</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<style>
    html, body {
        height: 100%;
        margin: 0;
        padding: 0;
    }
    #map {
        height: 60%;
        width: 60%;
    }
    #site-input {
        margin: 10px;
    }
    input {
        margin: 5px;
    }
    button {
        margin: 5px;
    }
</style>
</head>
<body>
<div id="site-input">
    Wd: <input type="text" id="site-width" value="5"><br>
    Ln: <input type="text" id="site-length" value="7"><br>
    Sp: <input type="text" id="site-spacing" value="5"><br>
    <button id="create-button">Create</button><br>
</div>
<div>
  <input id="origin" placeholder="origin" value="37.7695505,-122.4513206" />
  <input id="x" placeholder="x" value="37.7695722,-122.45114699" />
  <input id="heading" placeholder="heading" value="80.0" />
</div>
<div id="map"></div>
<script src="js.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?callback=initMap&libraries=geometry" async defer></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.3/jquery.min.js"></script>
</body>
</html>
</code>```

js.js

```<code>function initMap() {
  GMap = new google.maps.Map(document.getElementById('map'), {
    center: { lat: 37.76963799867498, lng: -122.45126726263503 },
    mapTypeId: google.maps.MapTypeId.SATELLITE,
    draggableCursor: 'crosshair',
    zoom: 20,
    disableDefaultUI: true
  });
  GMap.setTilt(0);

  var state = 0;    // 'origin', 'x'
  var heading = 0;  //   0 = heading north, 90 = heading east
  var originMarker = null;
  var xMarker = null;
  // polyline objects will be stored in these arrays
  var xLines = [];
  var yLines = [];

  // click on button
  google.maps.event.addDomListener(document.getElementById('create-button'), 'click', function() {
    removeAll();
    var latData = document.getElementById('origin').value.split(',');
    var lngData = document.getElementById('x').value.split(',');
    var pathPoints = [
      new google.maps.LatLng(parseFloat(latData[0]), parseFloat(latData[1])),
      new google.maps.LatLng(parseFloat(lngData[0]), parseFloat(lngData[1]))
    ];
    createGrid(pathPoints, GMap, xLines, yLines);
  });

  // click on map
  GMap.addListener('click', function(event) {
    var lat = event.latLng.lat();
    var lng = event.latLng.lng();
    switch (state) {
      case 0: // first click: user sets origin
        removeAll();
        originMarker = new google.maps.Marker({
          position: event.latLng,
          title: 'point A',
          map: GMap
        });
        // display
        document.getElementById('origin').value = lat +','+ lng;
        state++;
        break;
      case 1: // second click: now we can calculate the heading (heading = x-axis; heading +90° = y-axis)
        xMarker = new google.maps.Marker({
          position: event.latLng,
          title: 'point B',
          map: GMap
        });
        document.getElementById('x').value = lat +','+ lng;
        heading = google.maps.geometry.spherical.computeHeading(
          originMarker.getPosition(),
          xMarker.getPosition()
        );
        document.getElementById('heading').value = heading;
        var pathPoints = [
          {lat: originMarker.getPosition().lat(), lng: originMarker.getPosition().lng()},
          {lat: xMarker.getPosition().lat(), lng: xMarker.getPosition().lng()}
        ];
        createGrid([originMarker.getPosition(),xMarker.getPosition()], GMap, xLines, yLines);

        state = 0;
        break;

    }
  });
  //  remove all previous elements
  function removeAll() {

    if(originMarker) {originMarker.setMap(null);}
    if(xMarker) {xMarker.setMap(null);}
    for(var i in xLines) {xLines[i].setMap(null);}
    for(var i in yLines) {yLines[i].setMap(null);}

    state = 0;
    heading = 0;
    originMarker = null;
    xMarker = null;

    xLines = [];
    yLines = [];
  }

}

//
function createGrid(pathPoints, GMap, xLines, yLines) {
  var spacing = parseFloat(document.getElementById('site-spacing').value);
  var cols = parseInt(document.getElementById('site-width').value);
  var rows = parseInt(document.getElementById('site-length').value);

  var pointA = pathPoints[0];
  var pointB = pathPoints[1];
  var heading = google.maps.geometry.spherical.computeHeading(pointA, pointB);
  var distance = google.maps.geometry.spherical.computeDistanceBetween(pointA, pointB);

  for(var i=0; spacing && i<cols; i++) {
    // let's look for point C, on the line A-B, at a distance 'spacing' of point A
    // @see https://developers.google.com/maps/documentation/javascript/reference#MapTypeControlOptions
    // computeOffset(from:LatLng, distance:number, heading:number, radius?:number)

    var pointC = google.maps.geometry.spherical.computeOffset(pointA, i * spacing, heading);
    var pointD = google.maps.geometry.spherical.computeOffset(pointC, rows * spacing, heading - 90);

    //// put a test marker there
    //var marker = new google.maps.Marker({
    //  position: pointC,
    //  title: 'point C',
    //  map: GMap
    //});
    var pathPoints = [
      {lat: pointC.lat(), lng: pointC.lng()},
      {lat: pointD.lat(), lng: pointD.lng()}
    ];
    xLines[i] = polyline(pathPoints, GMap, '#00ff00');
  }

  for(var i=0; spacing && i<rows; i++) {
    var pointG = google.maps.geometry.spherical.computeOffset(pointA, i * spacing, heading - 90);
    var pointH = google.maps.geometry.spherical.computeOffset(pointG, cols * spacing, heading);
    //// put a test marker there
    //var marker = new google.maps.Marker({
    //  position: pointG,
    //  title: 'point G',
    //  map: GMap
    //});

    var pathPoints = [
      {lat: pointG.lat(), lng: pointG.lng()},
      {lat: pointH.lat(), lng: pointH.lng()}
    ];
    yLines[i] = polyline(pathPoints, GMap, '#00ff00');
  }

}

// returns a polyline object
function polyline(pathPoints, map, color) {
    // color
    if(typeof color == 'undefined') {
      color  ='#FF0000';
    }
    return new google.maps.Polyline({
      path: pathPoints,
      geodesic: true,
      strokeColor: color,
      strokeOpacity: 1.0,
      strokeWeight: 2,
      map: map
    });
}
</code>```

Body:
I have a html file that I included here. The file has text boxes and one push button. The push button will be activated in JavaScript file.

When the JavaScript runs it has an initialization section that loads the Google Maps tool to do certain measurements of a location or roof.

I need to create a function that will do the followings:
The existing code is already creating a square area or polygon. So idea is to create few smaller squares those will fit into the existing square in a straight line with small spaces in between of the squares.

I have attached the JavaScript code and highlighted the section where this new function or code should evolve.

I just started learning JavaScript specially google map API and I am stuck. Please assist me how I can implement this, it will be monumental help.

JavaScript file

// JavaScript source code

'use strict';
var mapScript = (function () {

    var GMap; // global variable within the solar module scope
    var squarePolys = []; //global array of Shape that will be attached to google maps

    function initMap() {
        // Load map at default location
        GMap = new google.maps.Map(document.getElementById('map'), {
            center: { lat: 37.76963799867498, lng: -122.45126726263503 },
            mapTypeId: google.maps.MapTypeId.SATELLITE,
            draggableCursor: 'crosshair',
            zoom: 20,
            disableDefaultUI: true
        });

        // force orthorgraphic imagery
        GMap.setTilt(0);

        // wait till map display is fully updated before drawing an area or roof section
        google.maps.event.addListenerOnce(GMap, "projection_changed", makeASite);

        //Hook up the
        var createButton = $("#create-button");
        createButton.click(function () {
            makeASite();
        });
    }

    //creating an area with modules
    function makeASite() {
        deletePreviousSite(); //removed any old polgyons first

        // draw default area or roof rectangle
        var rAreaSqPoly = constructRFSqPoly();
        squarePolys.push(rAreaSqPoly);

        // Create unites
        var unites = makeUnits(rAreaSqPoly);
        for (var i = 0; i < unites.length; i++) {
            squarePolys.push(unites[i]);
        }

        render();
    }

    // Create the default roof or an area rectangle
    function constructRFSqPoly() {
        //  The areas rectangle definition.
        //  Center:   the latitude, longitude location of the center of the rectangle
        //  Width:    width of rectangel in meters
        //  Height:   height of rectangel
        //  rotation: rotation angle of rectangle
        var rAreaSqPolyChoices = {
            center: new google.maps.LatLng(37.76963799867498, -122.45126726263503),
            width: 40.46, // meters
            length: 28.35,
            rotation: 20, // degrees
            color: '#0072ff',
            googleMap: GMap
        };

        // Create a google Shape object to overlay on the aerial
        return new Shape(rAreaSqPolyChoices);
    }

    // Create a list of pv module rectangles those will be later attached to the map
    function makeUnits(rAreaSqPoly) {
        var unitSqPolys = [];

        var unitWd = Number($("#site-width").val());
        var unitLn = Number($("#site-length").val());
        var unitSp = Number($("#site-spacing").val());

        ****Here I want to draw unites (square/polygon) on top of an
        exiting polygon (this could be a car parking lot or roof). The
        square are a straight line with spaces in between****

        return unitSqPolys;
    }

    // Redraws each Shape in the Shape list
    function render() {
        for (var i = 0; i < squarePolys.length; i++) {
            var Shape = squarePolys[i];
            Shape.clearMap();
            Shape.attachToMap();
        }
    }

    //Removes old Shapes from map and clears out the Shape list
    function deletePreviousSite() {
        for (var i = 0; i < squarePolys.length; i++) {
            var Shape = squarePolys[i];
            Shape.clearMap();
        }
        squarePolys = [];
    }

    var Shape = (function () { //This is the class definition for Shape
        //Width and length are in distance units,
        //Center is a google maps point in lat,lng coordinates
        //Rotation is in degress
        function Shape(options)
         { //This is the constructor for thos class
            // if(width !== "number" || length !== "number" || center !== "object", rotation !== "number")
            // throw new Error("Invalid arguments for constructing a Shape object");
            var _self = this;
            _self.width = options.width;
            _self.length = options.length;
            _self.center = options.center;
            _self.rotation = options.rotation;
            _self.googleMap = options.googleMap;
            _self.color = typeof options.color === "string" ? options.color : "#0072ff";
            _self.line = [];

            createShape();
            // In JavaScript member functions declared inside the contruction are private
            function createShape() {
                // Create rectangle coordinates, in latitude, longitude space to define an area or roof section of rectangle
                var line = [
                    Shape.setValuesInMtr(_self.center, _self.length / 2, -1 * _self.width / 2),
                    Shape.setValuesInMtr(_self.center, -1 * _self.length / 2, -1 * _self.width / 2),
                    Shape.setValuesInMtr(_self.center, -1 * _self.length / 2, 1 * _self.width / 2),
                    Shape.setValuesInMtr(_self.center, _self.length / 2, _self.width / 2)
                ];

                // Rotate the coordinates by the angle relative to the center of it
                _self.line = moveline(line, _self.rotation, _self.center);

                _self.googleMapsShape = new google.maps.Shape({
                    lines: _self.line,
                    strokeColor: _self.color,
                    strokeOpacity: 0.8,
                    strokeWeight: 2,
                    fillColor: _self.color,
                    fillOpacity: 0.35
                });
            }

            // Rotates an input array of latitude, longitude locations by the specified
            // angle around the specified latitude/longitude center
            function moveline(line, angle, origin) {
                var thisProjection = _self.googleMap.getProjection();

                var originPt = thisProjection.fromLatLngToPoint(origin);

                var moveOrders = line.map(function (latLng) {
                    var point = thisProjection.fromLatLngToPoint(latLng);

                    var rotatedLatLng = thisProjection.fromPointToLatLng(circulatePts(point, originPt, angle));
                    return rotatedLatLng;
                });
                return moveOrders;
            };

            // Rotation transformation
            function circulatePts(point, origin, angle) {
                var thisAngleR = angle * Math.PI / 180.0;
                return {
                    x: Math.cos(thisAngleR) * (point.x - origin.x) - Math.sin(thisAngleR) * (point.y - origin.y) + origin.x,
                    y: Math.sin(thisAngleR) * (point.x - origin.x) + Math.cos(thisAngleR) * (point.y - origin.y) + origin.y
                };
            }
        }

        //Attaches Shape to google maps
        Shape.prototype.attachToMap = function () { //public member function
            this.googleMapsShape.setMap(this.googleMap);
        };

        //Removes this Shape from google maps
        Shape.prototype.clearMap = function () { //public member function
            this.googleMapsShape.setMap(null);
        };

        // When provide a latitude, longitude location, and a distance north as well as east,
        // will return a new latitude, longitude location by the distances.
        Shape.setValuesInMtr = function (pointLatLng, nhMeters, eTMeters)
        { //Public static member function

            var R = 6378137; //PlanetEarth’s radius, sphere

            //offsets in radians
            var dLat = nhMeters / R;
            var dLon = eTMeters / (R * Math.cos(Math.PI * pointLatLng.lat() / 180));

            return new google.maps.LatLng(
                pointLatLng.lat() + dLat * 180 / Math.PI,
                pointLatLng.lng() + dLon * 180 / Math.PI);
        };

        return Shape
    })();

    return {
        initMap: initMap
    }
})();

<!DOCTYPE html>

    <title>Simple Map To Test</title>
    <meta name="viewport" content="initial-scale=1.0">
    <meta charset="utf-8">

        Wd: <input type="text" id="site-width" value="5">

        Ln: <input type="text" id="site-length" value="7">

        Sp: <input type="text" id="site-spacing" value="0">

        <button id="create-button">Create</button>

Body:
Okay, try this.

This is not the final form.  Look what happens, tell me which input and buttons you need ...

I made it (pretty much) from scratch, because it's easier for me to concentrate on the problem and forget all the rest.
Bu you should definitly put it back in your code format, with var mapScript = (function () { ...

The main weapon is the geometry library, which you have to load :
maps.googleapis.com/maps/api/js?callback=initMap&libraries=geometry
(again, in your code this would be mapScript.initMap )

it gives you

computeOffset (you give a point A, a distance and a heading, it returns point B)

computeHeading (you give a point A and point B, it returns the heading)

computeDistanceBetween (you give a point A and point B, it returns the distance)

instructions:

you can fill in point A and point B (the heading input is calculated, it doesn't change anything, it just tells you the angle)

or

click on the map, first for point A.  Click again for point B.  Then the function is automatically loaded, it reads the spacing/rows/cols data and makes the grid.

index.htm

<!DOCTYPE html>
<html>
<head>
<title>Simple Map To Test</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<style>
    html, body {
        height: 100%;
        margin: 0;
        padding: 0;
    }
    #map {
        height: 60%;
        width: 60%;
    }
    #site-input {
        margin: 10px;
    }
    input {
        margin: 5px;
    }
    button {
        margin: 5px;
    }
</style>
</head>
<body>
<div id="site-input">
    Wd: <input type="text" id="site-width" value="5"><br>
    Ln: <input type="text" id="site-length" value="7"><br>
    Sp: <input type="text" id="site-spacing" value="5"><br>
    <button id="create-button">Create</button><br>
</div>
<div>
  <input id="origin" placeholder="origin" value="37.7695505,-122.4513206" />
  <input id="x" placeholder="x" value="37.7695722,-122.45114699" />
  <input id="heading" placeholder="heading" value="80.0" />
</div>
<div id="map"></div>
<script src="js.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?callback=initMap&libraries=geometry" async defer></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.3/jquery.min.js"></script>
</body>
</html>

js.js

function initMap() {
  GMap = new google.maps.Map(document.getElementById('map'), {
    center: { lat: 37.76963799867498, lng: -122.45126726263503 },
    mapTypeId: google.maps.MapTypeId.SATELLITE,
    draggableCursor: 'crosshair',
    zoom: 20,
    disableDefaultUI: true
  });
  GMap.setTilt(0);

  var state = 0;    // 'origin', 'x'
  var heading = 0;  //   0 = heading north, 90 = heading east
  var originMarker = null;
  var xMarker = null;
  // polyline objects will be stored in these arrays
  var xLines = [];
  var yLines = [];

  // click on button
  google.maps.event.addDomListener(document.getElementById('create-button'), 'click', function() {
    removeAll();
    var latData = document.getElementById('origin').value.split(',');
    var lngData = document.getElementById('x').value.split(',');
    var pathPoints = [
      new google.maps.LatLng(parseFloat(latData[0]), parseFloat(latData[1])),
      new google.maps.LatLng(parseFloat(lngData[0]), parseFloat(lngData[1]))
    ];
    createGrid(pathPoints, GMap, xLines, yLines);
  });

  // click on map
  GMap.addListener('click', function(event) {
    var lat = event.latLng.lat();
    var lng = event.latLng.lng();
    switch (state) {
      case 0: // first click: user sets origin
        removeAll();
        originMarker = new google.maps.Marker({
          position: event.latLng,
          title: 'point A',
          map: GMap
        });
        // display
        document.getElementById('origin').value = lat +','+ lng;
        state++;
        break;
      case 1: // second click: now we can calculate the heading (heading = x-axis; heading +90° = y-axis)
        xMarker = new google.maps.Marker({
          position: event.latLng,
          title: 'point B',
          map: GMap
        });
        document.getElementById('x').value = lat +','+ lng;
        heading = google.maps.geometry.spherical.computeHeading(
          originMarker.getPosition(),
          xMarker.getPosition()
        );
        document.getElementById('heading').value = heading;
        var pathPoints = [
          {lat: originMarker.getPosition().lat(), lng: originMarker.getPosition().lng()},
          {lat: xMarker.getPosition().lat(), lng: xMarker.getPosition().lng()}
        ];
        createGrid([originMarker.getPosition(),xMarker.getPosition()], GMap, xLines, yLines);

        state = 0;
        break;

    }
  });
  //  remove all previous elements
  function removeAll() {

    if(originMarker) {originMarker.setMap(null);}
    if(xMarker) {xMarker.setMap(null);}
    for(var i in xLines) {xLines[i].setMap(null);}
    for(var i in yLines) {yLines[i].setMap(null);}

    state = 0;
    heading = 0;
    originMarker = null;
    xMarker = null;

    xLines = [];
    yLines = [];
  }

}

//
function createGrid(pathPoints, GMap, xLines, yLines) {
  var spacing = parseFloat(document.getElementById('site-spacing').value);
  var cols = parseInt(document.getElementById('site-width').value);
  var rows = parseInt(document.getElementById('site-length').value);

  var pointA = pathPoints[0];
  var pointB = pathPoints[1];
  var heading = google.maps.geometry.spherical.computeHeading(pointA, pointB);
  var distance = google.maps.geometry.spherical.computeDistanceBetween(pointA, pointB);

  for(var i=0; spacing && i<cols; i++) {
    // let's look for point C, on the line A-B, at a distance 'spacing' of point A
    // @see https://developers.google.com/maps/documentation/javascript/reference#MapTypeControlOptions
    // computeOffset(from:LatLng, distance:number, heading:number, radius?:number)

    var pointC = google.maps.geometry.spherical.computeOffset(pointA, i * spacing, heading);
    var pointD = google.maps.geometry.spherical.computeOffset(pointC, rows * spacing, heading - 90);

    //// put a test marker there
    //var marker = new google.maps.Marker({
    //  position: pointC,
    //  title: 'point C',
    //  map: GMap
    //});
    var pathPoints = [
      {lat: pointC.lat(), lng: pointC.lng()},
      {lat: pointD.lat(), lng: pointD.lng()}
    ];
    xLines[i] = polyline(pathPoints, GMap, '#00ff00');
  }

  for(var i=0; spacing && i<rows; i++) {
    var pointG = google.maps.geometry.spherical.computeOffset(pointA, i * spacing, heading - 90);
    var pointH = google.maps.geometry.spherical.computeOffset(pointG, cols * spacing, heading);
    //// put a test marker there
    //var marker = new google.maps.Marker({
    //  position: pointG,
    //  title: 'point G',
    //  map: GMap
    //});

    var pathPoints = [
      {lat: pointG.lat(), lng: pointG.lng()},
      {lat: pointH.lat(), lng: pointH.lng()}
    ];
    yLines[i] = polyline(pathPoints, GMap, '#00ff00');
  }

}

// returns a polyline object
function polyline(pathPoints, map, color) {
    // color
    if(typeof color == 'undefined') {
      color  ='#FF0000';
    }
    return new google.maps.Polyline({
      path: pathPoints,
      geodesic: true,
      strokeColor: color,
      strokeOpacity: 1.0,
      strokeWeight: 2,
      map: map
    });
}


问:
Some questions about Room and Paging Library
I am trying to set up all my lists with Room Persistance Library and Paging Library but I am facing some problems when implementing PagedListAdapter.

Question 1

I don't want to write any if, when... conditions in the onBindViewHolder so the scrolling is completely fluid. I have a model with its attributes. As an example, I want to set the visibility of a view that it is inside the layout (like a TextView) depending on a Boolean of the model, but I don't want to use an if. What would be the correct way of achieving that?

Should I create an Int attribute in the model which has the View.VISIBLE or View.GONE? But then the model can get very complex with lots of attributes and all of them are on all the model objects of the Room database.

Should I create another model which only has the attributes needed for the adapter UI? But then every time the real model is modified, I also have to modify the adapter model in order to see changes on the UI. And I think that's not good at all.

Do you know if there is somewhere where I can do this asynchronously in PagedListAdapter?

Question 2

I need to use functions like getString(R.string.resource), which requires a context. I also need to use Glide to load an image into an ImageView, but it requires an Activity context or Fragment context. I tried to inject it using dagger but that's not possible. It is safe to pass that context through the constructor? Or what is the best way of doing that?
(I suppose the same problem happens implementing RecyclerViewAdapter)

答:
In my studied application I have table which save the current player state. This table I use in multiselect queries, so when I change this table, Paging library  will change my DataSource. Example app.

I use Context instance from View instance with method View.getContext().


问:
Elements of the layout not showing in phone auto-rotate mode
I am participating in the Udacity Android Basics degree. I am struggling with the project explained below. I am yet using only basic knowledge so please do not be surprised by the code simplicity. :)) I am eager to understand how to position elements so that they appear in every phone orientation mode using RelativeLayout.

You can find the XML here.

There are two screenshots of the app displayed in portrait and auto-rotate. The portrait looks alright but in auto-rotate half of the information displayed disappears.

My second question is related to the clickable elements. Once, I made them clickable they turned into red and underlined. Is this common or I should offset this with another statement?

This is my GitHub project.
Any help is appreciated.

Thanks,
Iva

答:
For auto-rotation, you can either lock rotation for your app locking screen rotation. You can use any of the methods suggested by other developers.

But If you want to add landscape orientation to your app, then you will have to define a separate XML layout file for it. You can do so by Creating a
 layout-landdirectory by right clicking layout under res  and putting the landscape version of your layout XML file in that directory. You can also refer to this answer for some help handle screen rotation without losing data in android

Coming to the second part of your question, if you make an element clickable, it is not supposed to turn red and underlined. I am not sure how you are making them clickable but to make an element perform a function on Click, just declare the element and define it. Then you can set an OnClick listener to it. You can see an example here making a button clickable. Youcan also try this code to make the button clickable:

```<code> Button btn= (Button) findViewById(R.id.button_main);
    btn.setClickable(true);
</code>```

Body:
For auto-rotation, you can either lock rotation for your app locking screen rotation. You can use any of the methods suggested by other developers.

But If you want to add landscape orientation to your app, then you will have to define a separate XML layout file for it. You can do so by Creating a
 layout-landdirectory by right clicking layout under res  and putting the landscape version of your layout XML file in that directory. You can also refer to this answer for some help handle screen rotation without losing data in android

Coming to the second part of your question, if you make an element clickable, it is not supposed to turn red and underlined. I am not sure how you are making them clickable but to make an element perform a function on Click, just declare the element and define it. Then you can set an OnClick listener to it. You can see an example here making a button clickable. Youcan also try this code to make the button clickable:

 Button btn= (Button) findViewById(R.id.button_main);
    btn.setClickable(true);


问:
Unit testing react using Karma and Jasmine
I am very new to react and I have written a code using React 14 without any transpiler. Now I want to use Karma-Jasmine for unit testing but it seems that my test is failing rendering the app.

I have the following structure:

```<code>node_modules
MyApp/
    /js/ *.js
    /test/*.js
Karma.conf.js
package.json
index.html
</code>```

My index.html:

```<code><html>
<div id="content"></div>
<script src="js/react-0.14.7.js"></script>
<script src="js/react-dom-0.14.7.js"></script>

<script src="js/App.js"></script>
<script src="js/main.js"></script>
<link rel="stylesheet" href="style.css">
</body>
</html>
</code>```

My main.js:

```<code>ReactDOM.render(React.createElement(App), document.getElementById('content'))
</code>```

My App then is like below:

```<code>var h = React.createElement;

var Command = React.createClass({
   render: function(){
   return h(....)
  }
})
</code>```

my test code is as follows:

```<code>describe('App', function() {
beforeEach(function() {
fixture.load('index.htm');
});

beforeEach(function () {
ReactDOM.render(React.createElement(App),  document.getElementById('content'));
});

it('accepts elements', function() {
  document.getElementById('x').value = 1;
  document.getElementById('y').value = 2;
  document.getElementById('setbtn').click();
});

});
</code>```

And here is the error:

```<code>Uncaught ReferenceError: App is not defined
at main.js:2
(anonymous) @ main.js:2
debug.html:1 (WEB_PAGE context) Lazy require of app.binding did not set the binding field
.
.
.
ReferenceError: fixture is not defined
at UserContext.<anonymous> (main.test.js:6)
</code>```

Debugging Karma shows my files have been loaded as I can see the functions in my components. I installed Html2js and added to my Karma.conf.js. I have read most of the documents on the web but they didn't help.

What am I doing wrong? I

答:
Are you using js-fixtures?
Then you need to write:</p>

```<code>fixtures.load('index.htm'); // <--- fixtureS not fixture!
</code>```

Body:
I am very new to react and I have written a code using React 14 without any transpiler. Now I want to use Karma-Jasmine for unit testing but it seems that my test is failing rendering the app.

I have the following structure:

node_modules
MyApp/
    /js/ *.js
    /test/*.js
Karma.conf.js
package.json
index.html

My index.html:

<link rel="stylesheet" href="style.css">

My main.js:

ReactDOM.render(React.createElement(App), document.getElementById('content'))

My App then is like below:

var h = React.createElement;

var Command = React.createClass({
   render: function(){
   return h(....)
  }
})

my test code is as follows:

describe('App', function() {
beforeEach(function() {
fixture.load('index.htm');
});

beforeEach(function () {
ReactDOM.render(React.createElement(App),  document.getElementById('content'));
});

it('accepts elements', function() {
  document.getElementById('x').value = 1;
  document.getElementById('y').value = 2;
  document.getElementById('setbtn').click();
});

});

And here is the error:

Uncaught ReferenceError: App is not defined
at main.js:2
(anonymous) @ main.js:2
debug.html:1 (WEB_PAGE context) Lazy require of app.binding did not set the binding field
.
.
.
ReferenceError: fixture is not defined
at UserContext.<anonymous> (main.test.js:6)

Debugging Karma shows my files have been loaded as I can see the functions in my components. I installed Html2js and added to my Karma.conf.js. I have read most of the documents on the web but they didn't help.

What am I doing wrong? I

Body:
Are you using js-fixtures?
Then you need to write:

fixtures.load('index.htm'); // <--- fixtureS not fixture!