package editor import ( "bytes" "fmt" "log" "strings" ) // InputRepeater returns the []byte of an HTML element with a label. // It also includes repeat controllers (+ / -) so the element can be // dynamically multiplied or reduced. // IMPORTANT: // The `fieldName` argument will cause a panic if it is not exactly the string // form of the struct field that this editor input is representing // type Person struct { // item.Item // editor editor.Editor // // Names []string `json:"names"` // //... // } // // func (p *Person) MarshalEditor() ([]byte, error) { // view, err := editor.Form(p, // editor.Field{ // View: editor.InputRepeater("Names", p, map[string]string{ // "label": "Names", // "type": "text", // "placeholder": "Enter a Name here", // }), // } // ) // } func InputRepeater(fieldName string, p interface{}, attrs map[string]string) []byte { // find the field values in p to determine pre-filled inputs fieldVals := ValueFromStructField(fieldName, p) vals := strings.Split(fieldVals, "__ponzu") scope := TagNameFromStructField(fieldName, p) html := bytes.Buffer{} _, err := html.WriteString(``) if err != nil { log.Println("Error writing HTML string to InputRepeater buffer") return nil } for i, val := range vals { el := &Element{ TagName: "input", Attrs: attrs, Name: TagNameFromStructFieldMulti(fieldName, i, p), Data: val, ViewBuf: &bytes.Buffer{}, } // only add the label to the first input in repeated list if i == 0 { el.Label = attrs["label"] } _, err := html.Write(DOMElementSelfClose(el)) if err != nil { log.Println("Error writing DOMElementSelfClose to InputRepeater buffer") return nil } } _, err = html.WriteString(``) if err != nil { log.Println("Error writing HTML string to InputRepeater buffer") return nil } return append(html.Bytes(), RepeatController(fieldName, p, "input", ".input-field")...) } // SelectRepeater returns the []byte of a HTML element with a label. // It also includes repeat controllers (+ / -) so the element can be // dynamically multiplied or reduced. // IMPORTANT: // The `fieldName` argument will cause a panic if it is not exactly the string // form of the struct field that this editor input is representing func FileRepeater(fieldName string, p interface{}, attrs map[string]string) []byte { // find the field values in p to determine if an option is pre-selected fieldVals := ValueFromStructField(fieldName, p) vals := strings.Split(fieldVals, "__ponzu") addLabelFirst := func(i int, label string) string { if i == 0 { return `` } return "" } tmpl := `
%[2]s
Upload
` // 1=nameidx, 2=addLabelFirst, 3=val, 4=className, 5=fieldName script := `` // 1=nameidx, 2=className name := TagNameFromStructField(fieldName, p) html := bytes.Buffer{} _, err := html.WriteString(``) if err != nil { log.Println("Error writing HTML string to FileRepeater buffer") return nil } for i, val := range vals { className := fmt.Sprintf("%s-%d", name, i) nameidx := TagNameFromStructFieldMulti(fieldName, i, p) _, err := html.WriteString(fmt.Sprintf(tmpl, nameidx, addLabelFirst(i, attrs["label"]), val, className, fieldName)) if err != nil { log.Println("Error writing HTML string to FileRepeater buffer") return nil } _, err = html.WriteString(fmt.Sprintf(script, nameidx, className, val)) if err != nil { log.Println("Error writing HTML string to FileRepeater buffer") return nil } } _, err = html.WriteString(``) if err != nil { log.Println("Error writing HTML string to FileRepeater buffer") return nil } return append(html.Bytes(), RepeatController(fieldName, p, "input.upload", "div.file-input."+fieldName)...) } // RepeatController generates the javascript to control any repeatable form // element in an editor based on its type, field name and HTML tag name func RepeatController(fieldName string, p interface{}, inputSelector, cloneSelector string) []byte { scope := TagNameFromStructField(fieldName, p) script := ` ` return []byte(script) }