Results 1 to 8 of 8

Thread: DOM createElement/appendChild/etc generator?

  1. #1
    Join Date
    Apr 2008
    Location
    San Diego, CA
    Posts
    352
    Thanks
    57
    Thanked 6 Times in 6 Posts

    Default DOM createElement/appendChild/etc generator?

    Hi all,

    Does anyone know of a generator that will take markup input like so:

    Code:
    <div>
    	<p>
    		Hello world!
    	</p>
    </div>
    And output it like this?

    Code:
    oDiv = document.createElement("div");
    oP = document.createElement("p");
    oText = document.createTextNode("Hello world!");
    
    oP.appendChild(oText);
    oDiv.appendChild(oP);
    Sure would save some time!

  2. #2
    Join Date
    Jun 2008
    Posts
    589
    Thanks
    13
    Thanked 54 Times in 54 Posts
    Blog Entries
    1

    Default

    I have never seen one before. If it were to be created, someone would have probably used C/C++ or Java for a compiled program. I don't think so... By the way: your JS code is bad: you need var before those variables.

    Now, it may be possible for someone to make a JavaScript that will read an HTML file as XML (XHTML) to count the tags, their names, and their values. Maybe, just maybe...

    -magicyte
    Last edited by magicyte; 10-26-2008 at 12:46 AM.

  3. #3
    Join Date
    May 2007
    Location
    USA
    Posts
    373
    Thanks
    2
    Thanked 4 Times in 4 Posts

    Default

    Here's some Haskell code that does the job. I won't claim that it will parse any HTML, but it should be adequate. Also, my code does not check for legal HTML. That's your job. I did a little testing, but there may be bugs in it. If you find any or have any comments/suggestions just post a reply.


    Main.hs
    Code:
    module Main (
      ) where
    
    import Prelude hiding ((.))
    
    import System.Environment (getArgs)
    
    import ApplicativeParsec
    
    import Control.Monad.State
    
    import Data.List (intercalate)
    import Data.Char (toLower, toUpper)
    
    -----------------------------------------------------------
    
    main :: IO ()
    main = do
      args <- getArgs
      case args of 
        [] -> putStrLn "use: htmlToDom inputFile [outputFile]"
        file : dest -> let
          out = case dest of
            [] -> putStrLn
            file' : _ -> writeFile file'
          in readFile file >>= out . either show show . parse (spaces *> tag) ""
    
    -----------------------------------------------------------
    
    infixr 9 .
    (.) :: (Functor f) => (a -> b) -> f a -> f b
    (.) = fmap
    
    mapFst :: (a -> b) -> (a, c) -> (b, c)
    mapFst f (x, y) = (f x, y)
    
    compose :: [a -> a] -> (a -> a)
    compose = foldr (.) id
    
    -----------------------------------------------------------
    
    type Name = String
    type Attribute = (Name, String)
    type Text = String
    
    data Tag = Tag Name [Attribute] [Either Tag Text]
    
    instance Show Tag where
      showsPrec _ tag = snd $ evalState (showsTag tag) 0
        where
          ss = showString
          showsTag (Tag name attrs cs) = do
            num <- get
            modify (+1)
            (cIdents, innerDefs) <- unzip . mapM showsChild cs
            let ident = '$' : show num
                decl = ss "var " . ss ident . ss " = document.createElement(" . shows name . ss ");\n"
                appendChildren = compose $ map (
                  \cIdent -> let
                    arg = either ss (\txt -> ss "document.createTextNode(" . shows txt . ss ")") cIdent
                    in ss ident . ss ".appendChild(" . arg . ss ");\n"
                  ) cIdents
                setAttrs = compose $ map (
                  \(name, val) -> ss ident . ss ".setAttribute(" . shows name . ss ", " . shows val . ss ");\n"
                  ) attrs
            return (ident, compose innerDefs . decl . setAttrs . appendChildren)
          showsChild (Left tag) = mapFst Left . showsTag tag
          showsChild (Right txt) = return (Right txt, id)
    
    -----------------------------------------------------------
    
    ws :: [Char]
    ws = " \v\f\t\r\n"
    
    optionalWs :: CharParser st String
    optionalWs = option "" $ (: []) . oneOf ws 
    
    ichar :: Char -> CharParser st Char
    ichar c = oneOf [toUpper c, toLower c]
    
    istring :: String -> CharParser st String
    istring = mapM ichar
    
    brackets :: CharParser st a -> CharParser st a
    brackets p = char '<' *> p <* char '>'
    
    ident :: CharParser st Name
    ident = many1 alphaNum <* spaces
    
    tag :: CharParser () Tag
    tag = do
      (tagName, attrs, slash) <- brackets $ liftM3 (,,) ident attrs $ not . null . option "" (string "/")
      let mkTag = return . Tag tagName attrs
      if slash
        then mkTag []
        else (children >>= mkTag) <* istring tagName <* char '>'
      where
        children = manyTill (Left . tag <|> Right . text) $ try $ string "</"
     
    text :: CharParser st Text
    text = do
      space1 <- optionalWs
      spaces
      text <- intercalate " " . sepBy (many (noneOf $ '<' : ws)) (many1 space)
      space2 <- optionalWs
      spaces
      return $ space1 ++ text ++ space2
    
    attr :: CharParser st Attribute
    attr = do
      name <- many1 alphaNum
      char '='
      quote <- oneOf "'\""
      value <- manyTill anyChar $ char quote
      return (name, value)
    
    attrs :: CharParser st [Attribute]
    attrs = sepEndBy (try attr) (many1 space)
    ApplicativeParsec.hs
    Code:
    module ApplicativeParsec (
        module Control.Applicative
      , module Text.ParserCombinators.Parsec
      ) where
    
    import Control.Applicative
    import Control.Monad (MonadPlus(..), ap)
    import Text.ParserCombinators.Parsec hiding (many, optional, (<|>))
    
    instance Applicative (GenParser s a) where
      pure = return
      (<*>) = ap
    
    instance Alternative (GenParser s a) where
      empty = mzero
      (<|>) = mplus
    Last edited by Trinithis; 10-25-2008 at 09:14 AM.
    Trinithis

  4. #4
    Join Date
    Sep 2005
    Location
    India
    Posts
    1,627
    Thanks
    6
    Thanked 107 Times in 107 Posts

    Default

    I think you are looking for something like this:

    http://ejohn.org/blog/pure-javascript-html-parser/

    Hope this helps.

  5. #5
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    See:

    http://www.dynamicdrive.com/forums/s...2620#post52620

    Works best in FF, has some limitations. Good for most short snippets. Can handle most complex HTML markup if it is valid.
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  6. #6
    Join Date
    Jun 2008
    Posts
    589
    Thanks
    13
    Thanked 54 Times in 54 Posts
    Blog Entries
    1

    Default

    That is an ASTONISHING script!! I wonder how long it took for you to make it. Could you explain how you identified the HTML elements? I have an idea, but I am not so sure: did you split the strings between '<' and '>'? Just REALLY wondering...



    -magicyte

  7. #7
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    30,495
    Thanks
    82
    Thanked 3,449 Times in 3,410 Posts
    Blog Entries
    12

    Default

    The main job of writing this only took a number of hours, not sure how many, as it was some time ago. As with any complex script I write though, the process generally takes a number of days because I need to break it into phases and cannot always just switch gears at the drop of a hat to handle each phase (conception, writing, testing, etc.). I identified the HTML elements by their tagName property. If I were to write such a script today, I might prefer to use the nodeName property, though I would want to test out how that would work before committing to it. A well annotated version of the code (in two parts) starts here:

    http://www.dynamicdrive.com/forums/s...sion#post52536
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  8. #8
    Join Date
    Jun 2005
    Location
    英国
    Posts
    11,876
    Thanks
    1
    Thanked 180 Times in 172 Posts
    Blog Entries
    2

    Default

    If you're doing this, probably you should consider revising your script. I generally find it useful to simply clone the appropriate structure from a hidden node in the HTML. It's faster and easier.
    Twey | I understand English | 日本語が分かります | mi jimpe fi le jbobau | mi esperanton komprenas | je comprends franšais | entiendo espa˝ol | t˘i Ýt hiểu tiếng Việt | ich verstehe ein bisschen Deutsch | beware XHTML | common coding mistakes | tutorials | various stuff | argh PHP!

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •