123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- // The UXToolkit Project
- // Copyright (c) Wirecog, LLC. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license, which can be found in the LICENSE file.
-
- package cog
-
- import (
- "errors"
- "os"
- "path/filepath"
- "reflect"
- "strings"
-
- "go.isomorphicgo.org/go/isokit"
- "go.isomorphicgo.org/uxtoolkit/reconcile"
- _ "golang.org/x/net/html"
- "honnef.co/go/js/dom"
- )
-
- type UXCog struct {
- Cog
- cogType reflect.Type
- cogPrefixName string
- cogPackagePath string
- cogTemplatePath string
- templateSet *isokit.TemplateSet
- Props map[string]interface{}
- element *dom.Element
- id string
- hasBeenRendered bool
- parseTree *reconcile.ParseTree
- cleanupFunc func()
- }
-
- func (u *UXCog) getCogPrefixName() string {
-
- if u.cogType != nil {
- result := strings.Split(u.cogType.PkgPath(), string(os.PathSeparator))
- return "cog:" + result[len(result)-1]
- } else {
- return ""
- }
- }
-
- func (u *UXCog) ID() string {
- return u.id
- }
-
- func (u *UXCog) SetID(id string) {
- u.id = id
- }
-
- func (u *UXCog) SetCleanupFunc(cleanupFunc func()) {
- u.cleanupFunc = cleanupFunc
- }
-
- func (u *UXCog) SetElement(element *dom.Element) {
- u.element = element
- }
-
- func (u *UXCog) Element() *dom.Element {
- return u.element
- }
-
- func (u *UXCog) CogInit(ts *isokit.TemplateSet) {
-
- u.hasBeenRendered = false
- u.Props = make(map[string]interface{})
- if ts != nil {
- u.templateSet = ts
- }
- u.cogTemplatePath = filepath.Join(DefaultGoSourcePath, u.cogType.PkgPath(), DefaultTemplatesDirectoryName)
- u.cogPrefixName = u.getCogPrefixName()
-
- if isokit.OperatingEnvironment() == isokit.ServerEnvironment {
- u.RegisterCogTemplates()
- }
- }
-
- func (u *UXCog) TemplateSet() *isokit.TemplateSet {
- return u.templateSet
- }
-
- func (u *UXCog) SetTemplateSet(ts *isokit.TemplateSet) {
- u.templateSet = ts
- }
-
- func (u *UXCog) CogType() reflect.Type {
- return u.cogType
- }
-
- func (u *UXCog) SetCogType(cogType reflect.Type) {
- u.cogType = cogType
- }
-
- func (u *UXCog) CogTemplatePath() string {
- return u.cogTemplatePath
- }
-
- func (u *UXCog) SetCogTemplatePath(path string) {
- u.cogTemplatePath = path
- }
-
- func (u *UXCog) RegisterCogTemplates() {
- u.templateSet.GatherCogTemplates(u.cogTemplatePath, u.cogPrefixName, ".tmpl")
- }
-
- func (u *UXCog) GetProps() map[string]interface{} {
- return u.Props
-
- }
-
- func (u *UXCog) SetProp(key string, value interface{}) {
-
- u.Props[key] = value
- if ReactivityEnabled == true && u.hasBeenRendered == true {
- u.Render()
- }
-
- }
-
- func (u *UXCog) BatchPropUpdate(props map[string]interface{}) {
-
- for k, v := range props {
- u.Props[k] = v
- }
- if ReactivityEnabled == true && u.hasBeenRendered == true {
- u.Render()
- }
-
- }
-
- func (u *UXCog) RenderCogTemplate() {
-
- var populateRenderedContent bool
- if u.hasBeenRendered == false {
- populateRenderedContent = true
- } else {
- populateRenderedContent = false
- }
-
- rp := isokit.RenderParams{Data: u.Props, Disposition: isokit.PlacementReplaceInnerContents, Element: *u.element, ShouldPopulateRenderedContent: populateRenderedContent}
-
- u.templateSet.Render(filepath.Join(u.getCogPrefixName(), strings.Split(u.getCogPrefixName(), ":")[1]), &rp)
- if u.hasBeenRendered == false {
- u.hasBeenRendered = true
-
- D := dom.GetWindow().Document()
- cogRoot := D.GetElementByID(u.id).FirstChild().(*dom.HTMLDivElement)
- contents := cogRoot.InnerHTML()
- parseTree, err := reconcile.NewParseTree([]byte(contents))
- if err != nil {
- println("Encountered an error: ", err)
- } else {
- u.parseTree = parseTree
- }
-
- }
- }
-
- func (u *UXCog) Render() error {
- document := dom.GetWindow().Document()
- e := document.GetElementByID(u.ID())
-
- if u.hasBeenRendered == true && e == nil {
- if u.cleanupFunc != nil {
- u.cleanupFunc()
- return nil
- }
- }
-
- if strings.ToLower(e.GetAttribute("data-component")) != "cog" {
- return errors.New("The cog container div must have a \"data-component\" attribute with a value specified as \"cog\".")
- }
-
- if u.hasBeenRendered == false {
- // Initial Render
- u.SetElement(&e)
- u.RenderCogTemplate()
-
- return nil
- } else if u.element != nil {
- // Re-render
- if VDOMEnabled == true {
-
- rp := isokit.RenderParams{Data: u.Props, Disposition: isokit.PlacementReplaceInnerContents, Element: *u.element, ShouldPopulateRenderedContent: true, ShouldSkipFinalRenderStep: true}
-
- u.templateSet.Render(filepath.Join(u.getCogPrefixName(), strings.Split(u.getCogPrefixName(), ":")[1]), &rp)
- D := dom.GetWindow().Document()
- cogRoot := D.GetElementByID(u.id).FirstChild().(*dom.HTMLDivElement)
- //contents := cogRoot.InnerHTML()
- newTree, err := reconcile.NewParseTree([]byte(rp.RenderedContent))
-
- if err != nil {
- println("Encountered an error: ", err)
- }
-
- changes, err := u.parseTree.Compare(newTree)
- if err != nil {
- println("Encountered an error: ", err)
- }
- if len(changes) > 0 {
- changes.ApplyChanges(cogRoot)
- u.parseTree = newTree
- }
-
- } else {
- u.RenderCogTemplate()
-
- }
- return nil
- }
-
- return nil
-
- }
|