Exemplo n.º 1
0
Arquivo: patch.go Projeto: influx6/gu
// CreateFragment returns a DocumentFragment with the given html dom
func CreateFragment(html string) *js.Object {

	//if we are not in a browser,dont do anything.
	if !detect.IsBrowser() {
		return nil
	}

	// div := doc.CreateElement("div")
	div := CreateElement("div")

	//build up the html right in the div
	SetInnerHTML(div, html)

	//create the document fragment
	fragment := CreateDocumentFragment()

	//add the nodes from the div into the fragment
	nodes := ChildNodeList(div)
	ContextAppendChild(fragment, nodes...)

	//unwrap all the special Text UnknownELement we are using
	// UnWrapSpecialTextElements(fragment)

	return fragment
}
Exemplo n.º 2
0
// init intializes the internal state management variables used in dispatch.
func init() {
	if detect.IsBrowser() {
		history = History(HashSequencer)

		// Initiate to the current path.
		history.Follow(GetLocation())
	}
}
Exemplo n.º 3
0
// BrowserSupportsPushState checks if browser supports pushState
func BrowserSupportsPushState() bool {
	if !detect.IsBrowser() {
		return false
	}

	return (js.Global.Get("onpopstate") != js.Undefined) &&
		(js.Global.Get("history") != js.Undefined) &&
		(js.Global.Get("history").Get("pushState") != js.Undefined)
}
Exemplo n.º 4
0
Arquivo: app.go Projeto: influx6/gu
// New returns a new design.Resources activating the DOMRenderer if its gets called
// on the browser or else on the server.
func New() *design.Resources {
	if detect.IsBrowser() {
		return design.New(&redom.DOMRenderer{
			Document: dom.GetWindow().Document(),
		})
	}

	return design.New()
}
Exemplo n.º 5
0
Arquivo: raf.go Projeto: influx6/gu
// CancelAnimationFrame provides a cover for RAF using the
// js api cancelAnimationFrame.
func CancelAnimationFrame(id int, f ...func()) {
	if !detect.IsBrowser() {
		return
	}

	js.Global.Call("cancelAnimationFrame", id)

	for _, fx := range f {
		fx()
	}
}
Exemplo n.º 6
0
Arquivo: raf.go Projeto: influx6/gu
// RequestAnimationFrame provides a cover for RAF using the js
// api for requestAnimationFrame.
func RequestAnimationFrame(r Mux, f ...func()) int {
	if !detect.IsBrowser() {
		return -1
	}

	id := js.Global.Call("requestAnimationFrame", r).Int()

	for _, fx := range f {
		fx()
	}

	return id
}
Exemplo n.º 7
0
Arquivo: path.go Projeto: influx6/gu
// GetLocation returns the path and hash of the browsers location api else
// panics if not in a browser.
func GetLocation() (host string, path string, hash string) {
	if !detect.IsBrowser() {
		return
	}

	loc := js.Global.Get("location").String()
	ups, err := url.Parse(loc)
	if err != nil {
		return
	}

	host = ups.Host
	path = ups.Path
	hash = ups.Fragment
	return
}
Exemplo n.º 8
0
func panicBrowserDetect() {
	if !detect.IsBrowser() {
		panic("expected to be used in a dom/browser env")
	}
}
Exemplo n.º 9
0
Arquivo: raf.go Projeto: influx6/gu
func init() {
	if detect.IsBrowser() {
		rafPolyfill()
	}
}
Exemplo n.º 10
0
Arquivo: dom.go Projeto: influx6/govfx
// init initalizes properties and functions necessary for package wide varaibles.
func init() {
	if detect.IsBrowser() {
		initScrollProperties()
	}
}
Exemplo n.º 11
0
Arquivo: patch.go Projeto: influx6/gu
// Patch takes a dom string and creates a documentfragment from it and patches a existing dom element that is supplied. This algorithim only ever goes one-level deep, its not performant
// WARNING: this method is specifically geared to dealing with the haiku.Tree dom generation
func Patch(fragment, live *js.Object, onlyReplace bool) {

	//if we are not in a browser,dont do anything.
	if !detect.IsBrowser() {
		return
	}

	if !live.Call("hasChildNodes").Bool() {
		// if the live element is actually empty, then just append the fragment which
		// actually appends the nodes within it efficiently
		ContextAppendChild(live, fragment)
		return
	}

	shadowNodes := ChildNodeList(fragment)
	liveNodes := ChildNodeList(live)

	// FIXED: instead of going through the children which may be many,

patchloop:
	for n, node := range shadowNodes {
		if node == nil || node == js.Undefined {
			continue
		}

		if node.Get("constructor") == js.Global.Get("Text") {
			if _, empty := EmptyTextNode(node); empty {
				ContextAppendChild(live, node)
				continue patchloop
			}

			var liveNodeAt *js.Object

			if n < len(liveNodes) {
				liveNodeAt = liveNodes[n]
			}

			if liveNodeAt == nil || liveNodeAt == js.Undefined {
				ContextAppendChild(live, node)
			} else {
				InsertBefore(live, liveNodeAt, node)
			}

			continue patchloop
		}

		//get the tagname
		tagname := GetTag(node)

		// get the basic attrs
		var id, hash, class, uid string

		// do we have 'id' attribute? if so its a awesome chance to simplify
		if HasAttribute(node, "id") {
			id = GetAttribute(node, "id")
		}

		if HasAttribute(node, "class") {
			id = GetAttribute(node, "class")
		}

		// lets check for the hash and uid, incase its a pure template based script
		if HasAttribute(node, "hash") {
			hash = GetAttribute(node, "hash")
		}

		if HasAttribute(node, "uid") {
			uid = GetAttribute(node, "uid")
		}

		// if we have no id,class, uid or hash, we digress to bad approach of using Node.IsEqualNode
		if allEmpty(id, hash, uid) {
			AddNodeIfNone(live, node)
			continue patchloop
		}

		// eliminate which ones are empty and try to use the non empty to get our target
		if allEmpty(hash, uid) {
			// is the id empty also then we know class is not or vise-versa
			if allEmpty(id) {
				// log.Printf("adding since class")
				// class is it and we only want those that match narrowing our set
				no := QuerySelectorAll(live, class)

				// if none found we add else we replace
				if len(no) <= 0 {
					ContextAppendChild(live, node)
				} else {
					// check the available sets and replace else just add it
					AddNodeIfNoneInList(live, no, node)
				}

			} else {
				// id is it and we only want one
				// log.Printf("adding since id")
				no := QuerySelector(live, fmt.Sprintf("#%s", id))

				// if none found we add else we replace
				if no == nil || no != js.Undefined {
					ContextAppendChild(live, node)
				} else {
					ReplaceNode(live, node, no)
				}
			}

			continue patchloop
		}

		// lets use our unique id to check for the element if it exists
		sel := fmt.Sprintf(`%s[uid='%s']`, strings.ToLower(tagname), uid)

		// we know hash and uid are not empty so we kick ass the easy way
		targets := QuerySelectorAll(live, sel)

		// if we are nil then its a new node add it and return
		if len(targets) == 0 {
			ContextAppendChild(live, node)
			continue patchloop
		}

		for _, target := range targets {
			if onlyReplace {
				ReplaceNode(live, node, target)
				continue
			}

			//if we are to be removed then remove the target
			if HasAttribute(node, "NodeRemoved") {
				tgName := node.Get("tagName").String()

				// If its a tag in our header kdis, attempt to remove from head.
				if headerKids[tgName] {
					dom := js.Global.Get("document").Call("querySelector", "head")
					RemoveChild(dom, node)
				}

				// If its a script attempt to remove from head and body.
				if tgName == "script" {
					body := js.Global.Get("document").Call("querySelector", "body")
					head := js.Global.Get("document").Call("querySelector", "head")

					RemoveChild(head, node)
					RemoveChild(body, node)
				}

				// Lastly attempt to remove from target itself.
				RemoveChild(target, target)
				continue
			}

			// if the target hash is exactly the same with ours skip it
			if GetAttribute(target, "hash") == hash {
				continue
			}

			nchildren := ChildNodeList(node)

			//if the new node has no children, then just replace it.
			if len(nchildren) <= 0 {
				ReplaceNode(live, node, target)
				continue
			}

			//here we are not be removed and we do have kids

			//cleanout all the targets text-nodes
			CleanAllTextNode(target)

			//so we got this dude, are we already one level deep ? if so swap else
			// run through the children with Patch
			// if level >= 1 {
			// live.ReplaceChild(node, target)
			attrs := Attributes(node)

			for key, value := range attrs {
				SetAttribute(target, key, value)
			}

			children := ChildNodeList(target)
			if len(children) == 0 {
				SetInnerHTML(target, "")
				ContextAppendChild(target, nchildren...)

				// continue patchloop
				continue
			}

			Patch(node, target, onlyReplace)
		}
	}
}
Exemplo n.º 12
0
Arquivo: design.go Projeto: influx6/gu
// Init intializes all attached resources under its giving resource list.
func (rs *Resources) Init(useHashOnly ...bool) *Resources {
	var watchHash bool

	if len(useHashOnly) != 0 {
		watchHash = useHashOnly[0]
	}

	dispatch.Subscribe(func(pd dispatch.PathDirective) {
		if !watchHash {
			psx := dispatch.UseDirective(pd)
			if psx.String() == rs.lastPath.String() {
				return
			}

			rs.lastPath = psx

			if rs.renderer != nil {
				rs.renderer.Render(rs.Resolve(psx)...)
			}

			return
		}

		psx := dispatch.UseHashDirective(pd)
		if psx.String() == rs.lastPath.String() {
			return
		}

		rs.lastPath = psx

		if rs.renderer != nil {
			rs.renderer.Render(rs.Resolve(psx)...)
		}
	})

	var dslList []DSL

	collection.cl.Lock()
	{
		dslList = collection.collection
		collection.root = rs
		collection.collection = nil
	}
	collection.cl.Unlock()

	for _, dsl := range dslList {
		res := newResource(rs, dsl)
		res.Init()
	}

	collection.cl.Lock()
	{
		collection.root = nil
	}
	collection.cl.Unlock()

	if detect.IsBrowser() && rs.renderer != nil {
		du := rs.Resolve(dispatch.GetLocationHashAsPath())
		rs.renderer.Render(du...)
	}

	return rs
}