// We use https://github.com/xing/wysihtml5/ as open source rich text editor // func (self *RichTextArea) Render(ctx *Context) (err error) { if !Config.RichText.UseGlobalCSS { if self.ToolbarStylesheetURL != "" { debug.Print("Loading StylesheetURL") ctx.Response.RequireStyleURL(self.ToolbarStylesheetURL, 0) } else { debug.Print("Loading Config") ctx.Response.RequireStyleURL(Config.RichText.ToolbarCSS, 0) } } // ctx.Response.RequireStyleURL("http://yui.yahooapis.com/2.9.0/build/reset/reset-min.css", 0) // wysihtml5 parser rules ctx.Response.RequireScriptURL("/js/libs/wysihtml5-advanced.js", 0) // wysihtml5 Library ctx.Response.RequireScriptURL("/js/libs/wysihtml5-0.3.0.min.js", 1) ctx.Response.RequireScript(`var editor = new wysihtml5.Editor("`+self.id+`", { // id of textarea element toolbar: "wysihtml5-editor-toolbar", // id of toolbar element parserRules: wysihtml5ParserRules, // defined in parser rules set composerClassName: "wysihtml5-editor", stylesheets: ["`+Config.RichText.EditorCSS+`"] });`, 2) // ctx.Response.XML.Content(`<div id="wysihtml5-toolbar" style="display: none;">` + self.ToolbarHtml + `</div>`) ctx.Response.XML.Content(`<div id="wysihtml5-editor-toolbar" style="display: none;">` + Config.RichText.DefaultToolbar + `</div>`) // ctx.Response.XML.OpenTag("form") ctx.Response.XML.OpenTag("textarea") ctx.Response.XML.AttribIfNotDefault("id", self.id) ctx.Response.XML.Attrib("class", "wysihtml5 "+self.Class) cols := self.Cols if cols == 0 { cols = RichTextAreaDefaultCols } rows := self.Rows if rows == 0 { rows = RichTextAreaDefaultRows } ctx.Response.XML.Attrib("name", self.Name) ctx.Response.XML.Attrib("rows", rows) ctx.Response.XML.Attrib("cols", cols) ctx.Response.XML.AttribIfNotDefault("tabindex", self.TabIndex) ctx.Response.XML.AttribFlag("readonly", self.Readonly) ctx.Response.XML.AttribFlag("disabled", self.Disabled) ctx.Response.XML.AttribIfNotDefault("placeholder", self.Placeholder) ctx.Response.XML.Attrib("autofocus", "autofocus") ctx.Response.XML.EscapeContent(self.Text) ctx.Response.XML.CloseTagAlways() // ctx.Response.XML.CloseTagAlways() return nil }
func (self *setPostValuesStructVisitor) trySetFieldValue(field *model.MetaData) error { debug.Print(field) if self.form.IsFieldDisabled(field) || self.form.IsFieldExcluded(field, self.ctx) { return nil } switch s := field.Value.Addr().Interface().(type) { case model.Reference: // we don't handle references with forms yet return nil case *model.Bool: s.Set(self.ctx.Request.FormValue(field.Selector()) != "") return nil case *model.Blob: file, _, err := self.ctx.Request.FormFile(field.Selector()) if err != nil { return err } defer file.Close() bytes, err := ioutil.ReadAll(file) if err != nil { return err } s.Set(bytes) return nil case *model.File: file, header, err := self.ctx.Request.FormFile(field.Selector()) if err != nil { return err } defer file.Close() bytes, err := ioutil.ReadAll(file) if err != nil { return err } s.Name = header.Filename s.Data = bytes return nil case model.Value: s.SetString(self.ctx.Request.FormValue(field.Selector())) return nil } return nil }
// Pages and nil views will be registered with a trailing slash at their path // and a permanent redirect from the path without trailing slash // Nil views will be registered as NotFound404 // parentPath always ends with a slash func (self *ViewPath) initAndRegisterViewsRecursive(parentPath string) { if parentPath == "" || parentPath[len(parentPath)-1] != '/' { panic("Parent path must end with a slash: " + parentPath) } if parentPath != "/" && self.Name == "" && self.Args == 0 { panic("Sub path of " + parentPath + " with no Name and Args") } if self.Name != "" && !PathFragmentRegexp.MatchString(self.Name) { panic("Invalid characters in view.ViewPath.Name: " + self.Name) } if self.View != nil && utils.IsDeepNil(self.View) { panic("Nil value wrapped with non nil view.View under parentPath: " + parentPath) } addSlash := self.Args > 0 if self.View == nil { addSlash = true self.View = &NotFoundView{Message: "Invalid URL"} } else if _, isPage := self.View.(*Page); isPage { addSlash = true if self.Auth != nil { if self.NoAuth == nil && Config.LoginSignupPage != nil && *Config.LoginSignupPage != nil { self.NoAuth = IndirectURL(Config.LoginSignupPage) } } } path := parentPath + self.Name if self.Args > 0 { if self.Name != "" { path += "/" } for i := 0; i < self.Args; i++ { path += PathFragmentPattern + "/" } } if addSlash { if path[len(path)-1] != '/' { path += "/" } if path != "/" { web.Get(path[:len(path)-1], func(webContext *web.Context, args ...string) string { webContext.Redirect(http.StatusMovedPermanently, webContext.Request.RequestURI+"/") return "" }) } } if self.Args < 0 { panic("Negative Args at " + path) } if _, pathExists := viewsByPath[path]; pathExists { panic("View with path '" + path + "' already registered") } viewsByPath[path] = self.View if Config.Debug.PrintPaths { debug.Print(path) } //debug.Print(path) self.View.Init(self.View) if viewWithURL, ok := self.View.(ViewWithURL); ok { viewWithURL.SetPath(path) } htmlFunc := func(webContext *web.Context, args ...string) string { // See: http://groups.google.com/group/golang-nuts/browse_thread/thread/ab1971bb9459025d // Slows down the memory leak on 32 bit systems a little bit: defer func() { go runtime.GC() }() context := NewContext(webContext, self.View, args) for _, subdomain := range Config.RedirectSubdomains { if len(subdomain) > 0 { if subdomain[len(subdomain)-1] != '.' { subdomain += "." } host := context.Request.Host if strings.Index(host, subdomain) == 0 { host = host[len(subdomain):] url := "http://" + host + context.Request.URL.Path context.Redirect(http.StatusMovedPermanently, url) return "" } } } handleErr := func(err error) string { switch err.(type) { case NotFound: context.NotFound(err.Error()) case Redirect: if Config.Debug.PrintRedirects { fmt.Printf("%d Redirect: %s\n", http.StatusFound, err.Error()) } context.Redirect(http.StatusFound, err.Error()) case PermanentRedirect: if Config.Debug.PrintRedirects { fmt.Printf("%d Permanent Redirect: %s\n", http.StatusMovedPermanently, err.Error()) } context.Redirect(http.StatusMovedPermanently, err.Error()) case Forbidden: context.Abort(http.StatusForbidden, err.Error()) default: context.Abort(http.StatusInternalServerError, err.Error()) } return "" } handleNoAuth := func(err error) string { switch { case err != nil: return handleErr(err) case self.NoAuth != nil: from := url.QueryEscape(context.Request.RequestURI) to := self.NoAuth.URL(context.PathArgs...) + "?from=" + from return handleErr(Redirect(to)) } return handleErr(Forbidden("403 Forbidden: authentication required")) } if Config.OnPreAuth != nil { if err := Config.OnPreAuth(context); err != nil { return handleErr(err) } } if Config.GlobalAuth != nil { if ok, err := Config.GlobalAuth.Authenticate(context); !ok { return handleNoAuth(err) } } if self.Auth == nil { self.Auth = Config.FallbackAuth } if self.Auth != nil { if ok, err := self.Auth.Authenticate(context); !ok { return handleNoAuth(err) } } // numMiddlewares := len(Config.Middlewares) // for i := 0; i < numMiddlewares; i++ { // if abort := Config.Middlewares[i].PreRender(context); abort { // return "" // } // } xmlBuffer := utils.NewXMLBuffer() err := self.View.Render(context, &xmlBuffer.XMLWriter) // for i := numMiddlewares - 1; i >= 0; i-- { // html, err = Config.Middlewares[i].PostRender(context, html, err) // } if err != nil { return handleErr(err) } return xmlBuffer.String() } web.Get(path, htmlFunc) web.Post(path, htmlFunc) for i := range self.Sub { self.Sub[i].initAndRegisterViewsRecursive(path) } }