purescript-simple-dom
purescript-simple-dom copied to clipboard
Link modification example doesn't work
module Validator.Main where
import Control.Monad.Eff
import Data.DOM.Simple.Element
import Data.DOM.Simple.Window
import Data.DOM.Simple.Types
import Data.Traversable
import qualified Data.Array as A
modifyLinkTarget link = do
attr <- getAttribute "href" link -- attr = link.getAttribute("href")
setAttribute "href" "#" link -- link.setAttribute("href", "#")
setAttribute "data-target" attr link -- link.setAttribute("data-target", attr)
return link
modifyLinks page = do
links <- querySelectorAll "a" page -- links = [HTMLElement]
sequence $ A.map modifyLinkTarget links -- links.map(modifyLinkTarget)
main = do
doc <- document globalWindow
links <- querySelectorAll "a" doc -- links = [HTMLElement]
modifyLinks (links :: [HTMLElement])
pure unit
cody@cody-XPS-L521X:~/programming/purescript/validator$ grunt
Running "psc:all" (psc) task
>> Error creating file dist/example.js
>>
Warning: Error at src/Validator/Main.purs line 10, column 1 - line 16, column 1:
Error in declaration modifyLinkTarget
No instance found for Data.DOM.Simple.Element.Element u11318 Use --force to continue.
Aborted due to warnings.
You have to add a type signature. The compiler won't infer constraints so it gives you that error you got: https://github.com/purescript/purescript/wiki/Differences-from-Haskell#type-classes-and-type-inference
Also, your types don't line up in main. it should be: traverse modifyLinks links. For that matter, the last line of modifyLinks could be simplified to traverse modifyLinkTarget links. Or you could even make the whole function clearer with:
modifyLinks = querySelectorAll "a" >=> traverse modifyLinkTarget
After reading your above link, I added a top level signature and got modifyLinkTarget to type check. Here is the full code along with my new error:
module Validator.Main where
import Control.Bind
import Control.Monad.Eff
import Data.DOM.Simple.Element
import Data.DOM.Simple.Window
import Data.DOM.Simple.Types
import Data.Traversable
import qualified Data.Array as A
modifyLinkTarget :: HTMLElement -> forall eff b. Eff (dom :: Data.DOM.Simple.Types.DOM | eff) HTMLElement
modifyLinkTarget link = do
attr <- getAttribute "href" link -- attr = link.getAttribute("href")
setAttribute "href" "#" link -- link.setAttribute("href", "#")
setAttribute "data-target" attr link -- link.setAttribute("data-target", attr)
return link
modifyLinks = querySelectorAll "a" >=> traverse modifyLinkTarget
main = do
doc <- document globalWindow
-- links <- querySelectorAll "a" doc -- links = [HTMLElement]
-- modifyLinks (links :: [HTMLElement])
-- traverse modifyLinks links
pure unit
error:
Warning: Error at src/Validator/Main.purs line 18, column 1 - line 20, column 1:
Error in declaration modifyLinks
No instance found for Data.DOM.Simple.Element.Element u11343 Use --force to continue.
Aborted due to warnings.
Is it because I need to add a top level signature to modifyLinks as well? I'm going to look at it more later, but appreciate any direction or help you can give me.
Yep.
I believe I have the right type now.
modifyLinks :: HTMLDocument -> forall eff b. Eff (dom :: Data.DOM.Simple.Types.DOM | eff) [HTMLElement] -- line 19
modifyLinks = querySelectorAll "a" >=> traverse modifyLinkTarget
Does this error mean I have to create an instance of traverse for Element HTMLDocument?
Warning: Error at src/Validator/Main.purs line 19, column 1 - line 20, column 1:
Error in declaration modifyLinks
No instance found for Data.DOM.Simple.Element.Element Data.DOM.Simple.Types.HTMLDocument Use --force to continue.
I apologize if these questions are simple ones I should be able to figure out, I'm just having a hard time even after re-reading the relevant chapters in the purescript book. If you have any tutorials to recommend using traverse I'm guessing that would help me figure this problem out.
Thank you for your help and patience. Hopefully others will stumble onto this issue and it will answer their questions as well.
No worries. You want something like this:
module Validator.Main where
import Control.Monad.Eff
import Data.DOM.Simple.Document
import Data.DOM.Simple.Element
import Data.DOM.Simple.Window
import Data.DOM.Simple.Types
import Data.Traversable
import qualified Data.Array as A
modifyLinkTarget :: forall eff. HTMLElement -> Eff (dom :: _ | eff) HTMLElement
modifyLinkTarget link = do
attr <- getAttribute "href" link -- attr = link.getAttribute("href")
setAttribute "href" "#" link -- link.setAttribute("href", "#")
setAttribute "data-target" attr link -- link.setAttribute("data-target", attr)
return link
modifyLinks :: forall eff. HTMLElement -> Eff (dom :: _ | eff) [HTMLElement]
modifyLinks page = do
links <- querySelectorAll "a" page -- links = [HTMLElement]
sequence $ A.map modifyLinkTarget links -- links.map(modifyLinkTarget)
main = do
doc <- document globalWindow
links <- querySelectorAll "a" doc -- links = [HTMLElement]
traverse modifyLinks links
pure unit
Code compiling, but no links are being found:
module Validator.Main where
import Control.Monad.Eff
import Debug.Trace
import Data.DOM.Simple.Document
import Data.DOM.Simple.Element
import Data.DOM.Simple.Window
import Data.DOM.Simple.Types
import Data.Traversable
import qualified Data.Array as A
modifyLinkTarget :: forall eff. HTMLElement -> Eff (dom :: _ | eff) HTMLElement
modifyLinkTarget link = do
attr <- getAttribute "href" link -- attr = link.getAttribute("href")
setAttribute "href" "#" link -- link.setAttribute("href", "#")
setAttribute "data-target" attr link -- link.setAttribute("data-target", attr)
return link
modifyLinks :: forall eff. HTMLElement -> Eff (dom :: _ | eff) [HTMLElement]
modifyLinks page = do
links <- querySelectorAll "a" page -- links = [HTMLElement]
sequence $ A.map modifyLinkTarget links -- links.map(modifyLinkTarget)
main = do -- strangely I need the do here or I get an error
doc <- document globalWindow
links <- querySelectorAll "a" doc
trace $ "number of links: " ++ (show $ A.length links)
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<title>Example purescript app</title>
</head>
<body>
<script type="text/javascript" src="dist/example.js"></script>
<a href="">test link</a>
</body>
</html>
Console:
"number of links: 0"
Why aren't any links being matched?
Oh, it's because I had the link under the javascript :)
With the following html, nothing happens (the link isn't modified):
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<title>Example purescript app</title>
</head>
<body>
<a href="">test link</a>
<script type="text/javascript" src="dist/example.js"></script>
</body>
</html>
Is your actual code traverseing anything? If it's like above, then you haven't told it do modify anything.