package editor import ( "bytes" "fmt" "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 { // 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{} html.WriteString(``) 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"] } html.Write(domElementSelfClose(el)) } html.WriteString(``) 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{} html.WriteString(``) for i, val := range vals { className := fmt.Sprintf("%s-%d", name, i) nameidx := tagNameFromStructFieldMulti(fieldName, i, p) html.WriteString(fmt.Sprintf(tmpl, nameidx, addLabelFirst(i, attrs["label"]), val, className, fieldName)) html.WriteString(fmt.Sprintf(script, nameidx, className)) } html.WriteString(``) 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) }