Giter VIP home page Giter VIP logo

vash's Issues

Unexpected token .

I keep getting this issue when loading a view:

SyntaxError: Unexpected token .
    at Function (native)
    at Object.vash.link (C:\...\node_modules\vash\build\vash.js:1820:24)
    at VCompiler.VCP.generate (C:\...\node_modules\vash\build\vash.js:1262:22)
    at Object.compile (C:\...\node_modules\vash\build\vash.js:1323:10)
    at Object.vash.loadFile (C:\...\node_modules\vash\build\vash.js:2068:24)
    at View.vash.renderFile [as engine] (C:\...\node_modules\vash\build\vash.js:2078:8)
    at View.render (C:\...\node_modules\express\lib\view.js:76:8)
    at Function.app.render (C:\...\node_modules\express\lib\application.js:507:10)
    at ServerResponse.res.render (C:\...\node_modules\express\lib\response.js:831:7)
    at C:\...\app.js:36:9

The ... is me omitting the dir structure.

Anyway my index.vash file works fine, but if I try to load my dashboard.vash it blows up.

If it helps the app.js line 36 looks like:

app.get('/:module_name/', function (req, res) {
    var dashboardModel = {
        moduleName: req.params["module_name"].capitalize(),
        title: "...",
        description: "..."
    };
    res.render('dashboard', dashboardModel);
});

I will post info on the view itself if required but 99% of it is the same as the other pages which work fine, so was just wondering if you can see anything crazy off the top of your head which would cause this?

Are there any real world projects using Vash?

Trying to get a feeling on how "real" (i.e. non-example-only) templates would look like, I googled for real world projects using Vash and unfortunately found none.

So my question:

Are you aware of any (public) projects that are using Vash as the template engine (like e.g. a CMS)?

Express 4 support?

I am trying to upgrade to Express 4 but nothing is responding. I doubt Vash is the culprit but wanted to ask, is Express 4 even supported at all?

problems with @for (var item in model)

Nice project, been looking for a while to have something that allows client/server side templating with razor syntax.

However i ran into this problem pretty much right away, and it's a pretty classical way of using the razor syntax

Non working template

<script type="text/razor" id="template">
<ul>
    @for(var user in model) {
        <li>Hi my name is @user.Pseudo, and i'm @user.Age</li>
    }
</ul>
</script>
<div id="result"></div>

And the binding js

var users = [
    { Pseudo: "Robert", Age: 41 },
    { Pseudo: "Chris" , Age: 32 }
];

var tpl = vash.compile(document.getElementById('template').innerHTML);
document.getElementById('result').innerHTML = tpl(users);

And a working template, but syntax ugly and wouldn't work server-side

<script type="text/razor" id="template">
<ul>
    @for(var user in model) {
        <li>Hi my name is @model[@user].Pseudo, and i'm @model[@user].Age</li>
    }
</ul>
</script>
<div id="result"></div>

As you can see above, the use var gets cast to the index of the model item. Any chance this could be fixed, or did i miss something ?

Would be really awesome to be able to use razor everywhere, and would probably make a lot of dev's happy as currently there is no consistent way to do templating client/server-side aside switching to something like Nustache which feels more like a hack, and even jQuery templates / jsRender use a sorta mustache style syntax ..i love my razor :-)

Thank's
Robert

Exception when dividing

vash template:

@{
 var test = 100/3;
}
<span>@test</span>

UnmatchedCharacterError: Unmatched FORWARD_SLASH at line 4, character 14. Value: /
+PROGRAM
| +BLOCK
| | [NEWLINE (3,2): ]
| | [KEYWORD (4,0): var]
| | [WHITESPACE (4,3): ]
| | [IDENTIFIER (4,4): test]
| | [WHITESPACE (4,8): ]
| | [ASSIGN_OPERATOR (4,9): =]
| | [WHITESPACE (4,10): ]
| | [NUMERIC_CONTENT (4,11): 100]
| -BLOCK
-PROGRAM

Live binding integration layer

Hi.

How interested would you be in an integration layer for live binding? I've been working on integrating Vash for use with CanJS instead of its default EJS view engine and I've got a rudimentary version of live binding working with it.

E.g. I can have Vash process something like:

<h2>My would you look at the time:</h2>
@html.live( model, "time", function( model ) {
  <text>@model.time</text>
})

to have part of the view contents re-render whenever the 'time' property on the model changes, provided the model implements some kind of 'onchange' callback mechanism. In CanJS's case that means binding to the 'change' event on the model using model.bind( "change", function(){})

As this requires a DOM implementation and should hook into a not-further-specified 'observable model' implementation, it could only ever be done through exposing a generic integration layer that other frameworks should fill in themselves. However, it could prove to be a really powerful feature for clientside apps.

Gettin error "Object is not a function..." when using @html.extend

I have a layout.vash and index.vash in the same folder (i.e. they are siblings). The content of the files is as follows:

vash

Error: Problem while rendering template at line 4, character 5. Original message: object is not a function. Context: 2 | @html.block('content', function(model){ 3 |

Welcome to

> 4 | }) 5 | })

Block/append/prepend does not work in @html.include'd files.

main.js

var vash = require('vash');
var fs = require('fs');

var pageText = fs.readFileSync('page.vash').toString();
var page = vash.compile(pageText);
console.log(page());

layout.vash

<html>
    <head>
        @html.block('scripts')
    </head>
    <body>
        @html.block('content')
    </body>
</html>

page.vash

@html.extend('layout.vash', function(model) {
    @html.block('scripts', function() {
        <script>'Page script'</script>
    })

    @html.block('content', function() {
        <div>
            @html.include('component.vash')
        </div>
    })
})

component.vash

@html.append('scripts', function() {
    <script>'Component script'</script>
})

<p>Hello!</p>

As a result, <script>'Component script'</script> does not get rendered.
Why do I need this? Well, I wanted the component to automatically include specific scripts and styles, because I don't want to manually include them on each page where the component is used.
Is this supposed to work? I expected it to.

RFC: Changes coming in vash 0.8.x

I'm currently in the process of rewriting vash to be more extensible and stable, and to fix a few bugs (#26 especially, #27 to an extent) that are currently neigh unfixable or would be huge hacks with the current architecture. While the parser is becoming more complex, the lexer and compiler are becoming much more simple. In addition, vash will gain true HTML awareness, including HTML attributes and proper void tag support.

Syntax-wise, a template that compiled with 0.7 should compile with 0.8. I also plan to keep the 0.7 branch around for awhile until 0.8 stabilizes, assuming I get some feedback. I'll reply back here when the 0.8 branch is created and ready for testing (the ksh/stated branch is close, but you'll have to require('vash/experiments/stated') with a local repo to get things working).

The current work is being done here: https://github.com/kirbysayshi/vash/tree/ksh/stated/experiments/stated. All tests are currently passing (some with a few modifications), and I plan to move these files into their true home (/src or maybe /lib) very soon to being shoring up the build steps final patterns for third party inclusion.

Since this is all brand new, I also want to take some time to revisit a few things:

Build Process / Shipped Builds

Currently quite custom, manually concatenating everything. The 0.8 version will be using CJS, and thus in nodejs the code will just be the files (require('vash') will point at an index.js instead of a build/vash.js), while in browserland I'll ship builds using browserify and its standalone flag. I assume those using AMD will be able to consume vash just fine through the use of a shim or configuration. And if browserify is being used by a consumer they'll just be able to require('vash') or require('vash/runtime') with no configuration required.

Helper System / Runtime

The helper and buffer API will be remaining the same, but I'd like to enable browser builds to just require('vash/runtime') followed by requireing whatever helpers they actually need. This will likely entail adding a registerHelper method to the runtime or something similar. I'm open to ideas! In addition, I'd like to remove the 'masquerading as full vash' the runtime currently does, but not sure if it's possible without large api changes.

AST

I know of no tools that rely on vash 0.7's concept of an AST, but if there are, they will be completely broken in 0.8. I've created an AST format that is much closer to the SpiderMonkey AST format, although simplified and augmented to be able to handle HTML. It's simplified in the sense that vash does not need full JS knowledge. Please let me know if this is a concern for any tools I do not know about.

Streaming file support

This is not implemented yet, but I planned on vash being able to stream a file while parsing / lexing, instead of it's current "buffer the whole file" before parsing. The ground work is there, it's more a matter of hooking it up to some actual streaming files and smoothing out the rough edges. Except in cases of very large templates, this is more of a neat feature than a must-have.

Tilde-slash

I was getting spoiled by ASP.NET MVC 5's automatic detection of tilde-slash at the beginining of src and href attributes.

<link rel="stylesheet" type="text/css" href="~/Content/css/theme.css">

Now I realize that Vash doesn't do this but I was wondering what the best path should be in the mean time. I was at first going to take the template-transformed output and do a .replace() to find all instances equals-double-quote-tilde-slash with the virtual path of the root of the node application, but being still green to NodeJS and ExpressJS I'm still green on knowing the cleanest path to accomplishing that.

I suppose in the mean time I can create a vash helper equivalent to @Url.Content("..") in my own environment.

How to change default extension

Hi,

I want to change the extension ".vash" to ".html". I google it, and get some information.


#6
c9cb877

app.engine('html', vash.__express);


But it is not work now. I run nodejs with express. Could you tell me how to do it. thank you very much.

runtime and runtime-all builds are not wrapped for AMD

Currently only the 'vash' build target is wrapped for use as a CommonJS or CommonJS AMD module. The 'vash-runtime' and 'vash-runtime-all' build targets are not, which is problematic when you have an application that switches between 'vash' + text templates for development and 'vash-runtime(-all)' + precompiled templates for deployment.

Integration hooks for various layout strategies

Summary: Vash currently supports jade-style blocks, but other strategies need to be possible too, like WebPages (@html.renderBody(), @html.section(), @html.isSectionDefined()). This should be accomplished via unobtrusive hooks.

As stated in #8, my main goal is:

  • The view engine bits need to be optional, meaning the compiled templates know basically nothing of the larger system

What would be awesome:

  • vash.helpers.layout turns into vash.ViewEngine, and is a consumer of vash.

So I want to add points of integration, whether they be:

  1. callbacks
  2. events
  3. the concept of a parentContext that can be passed in manually (or just "another context")
  4. being able to manually pass in a Helpers instance
  5. instruct a template to return the Helpers instance instead of the rendered string
  6. Other ideas?

I have local code that implements 2, 3, 4, 5 via a second options parameter to a template. Events are implemented as a simple vash.asEvented which is used as a mixin to a vash.helpers (or any other prototype or instance).

Any thoughts or suggestions are greatly appreciated!

Node.js - express: where is the error? Make error more informative

var vash = require("vash");
vash.config.debugParser = true;
vash.config.debugCompiler = true;
vash.config.useWith = true;

Browser output:

TypeError: object is not a function
   at ~\node_modules\vash\build\vash.js:2213:4
   at Object.vash.loadFile (~\node_modules\vash\build\vash.js:2072:10)
   at helpers.extend (~\node_modules\vash\build\vash.js:2190:8)
   at eval (eval at <anonymous> (~\node_modules\vash\build\vash.js:1820:24), <anonymous>:9:21)
   at linked (~\node_modules\vash\build\vash.js:1860:12)
   at ~\node_modules\vash\build\vash.js:2082:21
   at Object.vash.loadFile (~\node_modules\vash\build\vash.js:2070:10)
   at View.vash.renderFile [as engine] (~\node_modules\vash\build\vash.js:2078:8)
   at View.render (~\node_modules\express\lib\view.js:93:8)
   at EventEmitter.app.render (~\node_modules\express\lib\application.js:530:10) 

I do not see where is the error occurred. Neither in browser or in console.

What object?
Where is it?
What line?

Node v.11.13, vash 0.7.12-1

Block Rendering Issue

I'm running a simple test using node, reading the contents of a .vash file which references a layout which includes one block. I then compile and execute the file read in, and everything seems to run without any runtime errors, however the output for the block only displays [VASHMARK-7668312:block-content]

I'm sure I'm missing something simple, but I thought a quick review from the expert might shortcut some digging.

I've posted the example here: https://bitbucket.org/trankin/vash-testing.git

How to call partials or tags ?

Not an issue, but more a question:

EJS calls them partiels, I personally like to call them tags.

How to reuse template logic with Vash ?

Compile time (Function) errors are reported as 'while rendering'

If an error is encountered when evaling a template, the same reportError function is used with erroneously reports that the error occurred while rendering instead of at compile time. Compile time should have better message. Exact error reporting will be impossible (you cannot partially syntax check code without something like esprima), but it will be better than a message that is just plain wrong.

Running Vash on non-Node environments

After a whole day of trying to get Vash up and running in V8 within a .NET ClearScript application, I do have the following results:

  • It runs successfully for single-file-based templates.
  • It fails with error "Cannot call method 'normalize' of undefined" on a path.normalize call when using template includes through @html.include.

Even after debugging the Vash sources (through the Install Google Chrome Developer Tools for Java plug-in in Eclipse), I still cannot find a way to see what's going on here.

ClearScript

ClearScript is an implementation of V8 that runs "inside" a .NET application and makes binding to .NET objects from JavaScript easy and fast.

What I did

Since ClearScript is neither Node.js nor a browser, I created some .NET mockup classes for simulating e.g. the path or the fs variables.

Still, the above error.

I also tried to temporarily modify my local "vash.js" file but without any reasonable result.

My question

Do you think it is possible at all to use Vash in an environment that is neither browser nor Node.js?

Dots in regex literals break the parser

The following code throws a parser error:

vash.compile("<b>@model.replace(/./, 'b')</b>")("x")

Running this throws:

This is typically caused by an unmatched character or tag. Parse tree follows:
 +PROGRAM
 | +EXPRESSION
 | | +EXPRESSION
 | | | [OPERATOR (1,18): /]
 | | -EXPRESSION
 | -EXPRESSION
 | +EXPRESSION
 | | +EXPRESSION
 | | -EXPRESSION
 | -EXPRESSION
 | +EXPRESSION
 | | +EXPRESSION
 | | -EXPRESSION
 | -EXPRESSION
 | +EXPRESSION
 | | +EXPRESSION
 | | -EXPRESSION
 | -EXPRESSION
 | +EXPRESSION
 | | +EXPRESSION
 | | -EXPRESSION
 | -EXPRESSION
...

The tree is 1,000+ lines long

If I replace the . with ordinary characters, it works; if I replace it with other special characters (eg, <, "), it throws different parse errors.

It looks like the parser is not aware of regex literals

Auto-HTML Encoding

In Razor, rendered data is HTML encoded by default. Usage of the @: or tokens will render raw unencoded HTML. Though it does support these special tokens, Vash does not auto-encode anything at the moment.

Inline array declaration doesn't compile

Im happy to see some razor goodness make its way to javascript, although my very first example template seems to have hit a bug

It doesn't seem to like the @[1,2,3].forEach(...). It works fine if I read the array from my model, its just when i define it inline. I would think inline array declarations would be common enough to be supported (I apologize if i'm doing something wrong here)

<html>
    <head></head>
    <body>
        @[1,2,3].forEach(function(i){
            <p>@i number AH AH AH</p>
        })
    </body>
</html>

Anything similar to the app root symbol ~ in vash?

So for example in Razor I can do:

@Url.Content("~/Scripts/SomeScript.js")

Which would basically allow me to always know that it will be looking for Scipts in the root directory.

Reason I ask is I have some partials (other vash files which are included in the view) which may be called from different routes i.e /some-route and /some-route/some-child/some-other-child. So I want to be able to re-use this partial in all the views regardless of the route to them, as when it gets spat into the html page ./Scripts/SomeScript.js would be a completely different place on each of those routes.

Add support for CSS files

I'm currently trying to use Vash for CSS files. Simple things work:

p {
    background-color: @model.color;
}

Other things raise an exception during rendering:

p {
    @if(model.can=='123') {
        float-offset: 3px;
    } else {
        float-offset: 6px;
    }
}

There is a guy over at Code Project that modified Razor to work on CSS files.

Is something like this possible with Vash, too?

Adding Express rendering methods

First of all, kudos on this project!

Vash is only a "template-maker" at the moment, and can't be used with Express out of the box (that I know of? :P)

https://github.com/elmerbulthuis/jshtml/blob/master/index.js
That file (and in particular, the .render method) makes the lexer of that Razor renderer an actual template engine that is compatible with Express.

I would greatly appreciate the option of being able to integrate Vash with Express :)

How to run benchmarks ?

from Vash,
I am running

node support/build.js && node test/vash.test.js

it fails with

node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: Cannot find module 'uglify-js'
at Function._resolveFilename (module.js:332:11)
at Function._load (module.js:279:25)
at Module.require (module.js:354:17)
at require (module.js:370:17)
at Object. (/Users/orefalo/GitRepositories/Vash/support/build.js:2:12)
at Module._compile (module.js:441:26)
at Object..js (module.js:459:10)
at Module.load (module.js:348:31)
at Function._load (module.js:308:12)
at Array.0 (module.js:479:10)

Not able to use semicolons for proper JavaScript in blocks

Supposed I have the following file index.vash:

@html.extend('layout', function (model) {
  @html.block('content', function (model) {
    <p>Hallo Welt!</p>
  })
})

Then the code is "broken" due to missing semicolons at the end of the two lines containing the }) characters. But if I add them I won't get the result I'd like to, as they are sent to the client instead.

How to fix this?

Vash and Express

Hello,
I try to use the vash template engine (v0.5.9-1739) on express framework (3.0.3) and always receive exception.

code here: https://gist.github.com/4199454
platform: windows 8, 64-bit

Express
500 Error: ENOENT, no such file or directory 'd:\projects\wot\views\d:\projects\wot\views\index.vash'
at Object.fs.openSync (fs.js:338:18)
at Object.fs.readFileSync (fs.js:182:15)
at Object.vash.loadFile (d:\projects\wot\node_modules\vash\build\vash.js:418:23)
at View.vash.renderFile as engine
at View.render (d:\projects\wot\node_modules\express\lib\view.js:75:8)
at Function.app.render (d:\projects\wot\node_modules\express\lib\application.js:500:10)
at ServerResponse.res.render (d:\projects\wot\node_modules\express\lib\response.js:716:7)
at exports.index (d:\projects\wot\routes\index.js:7:7)
at callbacks (d:\projects\wot\node_modules\express\lib\router\index.js:160:37)
at param (d:\projects\wot\node_modules\express\lib\router\index.js:134:11)

Thanks!

Error "has no method forEach" when receiving JSON array back from REST service

I have a simple REST service that sends back a JSON object of preferences and when I try to render these with the following code it fails with "Object has no method 'forEach'".

_SENDING THE REQUEST_*
var getReq = http.get('http://localhost:8081/prefs', fuction(response){
  response.on('data', function(data){
    console.log(data); //AT THIS LINE DATA PRINTS OUT AS A BUFFER OF INTS
    res.render('preferences', {title : 'Preferences', prefs : data});
  });
});

***_THE VIEW (preferences.vash)_
@html.extend('layout', function(model){
  @html.block('body', function(model){
    @model.prefs.forEach(function(pref){ <----THIS LINE THROWS THE ERROR
      <div>@pref.name</div>
    })
  })
})

**_RETURNED JSON OBJ_
[{
'name' : 'blah1'
}, {
'name' : 'blah2'
}, {
'name' : 'blah3'
}]

I am new to node and javascript in general so maybe this is not a bug but an error on my part. If so could someone please explain the issue?

Unmatched BRACE_OPEN error when using ) in blocks

Supposed you have this file as layout.vash

<!doctype html>
<html>
  <head>
    <title>dotnetpro-Store</title>
  </head>

  <body>
    @html.block('content')
  </body>
</html>

and this file as index.vash:

@html.extend('layout', function (model) {
  @html.block('content', function (model) {
    <p>Hello world :-)!</p>
  })
})

Then rendering of index.vash crashes with the following error message:

UnmatchedCharacterError: Unmatched BRACE_OPEN at line 1, character 40. Value: {

The problem is the ) character in the text that shall be printed out. It does not matter whether it's a smiley or something else - as soon as there is a closing brace, the template can not be rendered.

How to solve this?

PS: Of course, a similar problem happens when using the } character.

Layout helpers cannot handle empty files (and misreport errors)

Being as I'm new to vash (and for that matter nodejs development) I might have overlooked something, but while the vash-express-sample demonstrates using @html.include() without issue in a view, it doesn't work when @html.include() is used in the layout file. I ran into this problem first in my own app and sought to validate that the issue is reproducible in the sample. It is. Perhaps this is by design, or perhaps there is a workaround?
The referenced partial is a sometimes-used feature that other layout files might reuse.

500 TypeError: object is not a function
    at C:\Users\jdavis\vash\vash-express-example\node_modules\vash\build\vash.js:575:13
    at Object.vash.loadFile (C:\Users\jdavis\vash\vash-express-example\node_modules\vash\build\vash.js:565:10)
    at View.vash.renderFile [as engine] (C:\Users\jdavis\vash\vash-express-example\node_modules\vash\build\vash.js:571:8)
    at View.render (C:\Users\jdavis\vash\vash-express-example\node_modules\express\lib\view.js:75:8)
    at Function.app.render (C:\Users\jdavis\vash\vash-express-example\node_modules\express\lib\application.js:505:10)
    at ServerResponse.res.render (C:\Users\jdavis\vash\vash-express-example\node_modules\express\lib\response.js:718:7)
    at exports.index (C:\Users\jdavis\vash\vash-express-example\routes\index.js:7:7)
    at callbacks (C:\Users\jdavis\vash\vash-express-example\node_modules\express\lib\router\index.js:162:37)
    at param (C:\Users\jdavis\vash\vash-express-example\node_modules\express\lib\router\index.js:136:11)
    at pass (C:\Users\jdavis\vash\vash-express-example\node_modules\express\lib\router\index.js:143:5)

Add support for async templates using promises

Use case:

Template:

<div>
    ...some template...
    @html.image("images/someIcon.png")
</div>

Code:

vash.helpers.image = function(url, alt) {
    // Compute a hash of the image
    // Return a Q promise of an <img> tag with a height, width, and cache-busted URL
};

var asyncTemplate = vash.compileAsync(templateText);
asyncTemplate(someModel)
     .then(function(resultHTML) { .... });

It would be very nice to have an asynchronous version of Vash. I'd like to be able to call asynchronous helper functions that return promises in a template. The compiled template function would itself return a Q promises of the entire template.

Since this would be used differently than regular templates, it would need to have a separate compileAsync function, which would generate template functions that always return promises.
Alternatively, the template could specify @async to indicate that it should be compiled into a promise-generating function. However, I think that would be a bad idea; the consumer of the template should know in advance what it expects.

Since the compiler has no way of knowing which expressions return promises, it would need to compile every expression into a then() call; the compiled code would look like this:

function async(model, html) {
    html = html || vash.helpers;
    html.__vo = html.__vo || [];
    var __vo = html.__vo;
    html.model = model;

    __vo.push("First block of static content");

    return Q.when(firstExpression)
        .then(function(result) {
            __vo.push(html.escape(result));
            __vo.push("Second block of static content")
            return secondExpression;
        })
        .then(function(result) {
            __vo.push(html.escape(result));
            __vo.push("Final block of static content")
            return __vo.join('');
        })
        .fin(function() {
            delete html.__vo;
        });
}

Possible to access Node.js functionality inside a template?

While currently evaluating your (great!) engine inside a Node.js test project, I tried the following (although not sure whether I really need it) inside a .vash template file:

@{
    var fs = require('fs');

    // ...more code...
}

This results in an error message

require is not defined.

My question: Is this something that is simply not possible and/or am I totally misusing the idea of a template engine?

I have problem using SAVE .

I have model like this.

var Contacts=can.Model({

    findAll:'GET /contacts',
    create:"POST /contacts",
    destroy : 'DELETE /contacts',
    update:'PUT /contacts/{id}',
    contacts : [],
    id : "",
    cname : "",
    address : "",
    phoneNo : "",
    emailId : "",
    category : "",
    contactdeleted:"",
    contactedited:"",
    newcontact:"",
    init : function(data,options){
        this.id = data.cname;
        this.cname = data.cname;
        this.address =  data.address;
        this.phoneNo =  data.phoneNo;
        this.emailId =  data.emailId;
        this.category =  data.category;
    }
},{});

My index page:

<!DOCTYPE html>
<html lan="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="stylesheet" href="css/index.css"/>
    <link rel="stylesheet" href="css/jqueryUi.min.css"/>
</head>
<body class="Contacts-app">
    <div class="container">
        <div class="header-section"></div>
        <div class="main-content">
            <button id="delete">Delete</button>
            <div class="main"></div>
            <div class="categories"></div>
        </div>  
            <div class="category-members"></div>    
        </div>
    </div>
    <div class="footer"></div>
    <div class="new-contact"></div>
    <div class="contact-details"></div>
    <script type="text/javascript" src="js/jquery.js"></script>
    <script type="text/javascript" src="js/can.jquery-1.1.3.js"></script>
    <script type="text/javascript" src="js/jquery-ui.js"></script>
    <script type="text/ejs" src="js/ejs.js"></script>
    <script type="text/javascript" src="js/can.fixture.js"></script>
    <script type="text/javascript" src="json/contacts.json"></script>
    <script type="text/javascript" src="models/Contacts.js"></script>
    <script type="text/javascript" src="control/controller.js"></script>
</body>
</html>

And my js page is:

(function() {

    //header controller
    var headerControl = can.Control({
        init: function(element, options) 
        {
            this.element.append(can.view('views/header.ejs', {}));
        }
    });


    //Observer for contacts 
    contactsObserver = new can.Observe({});


    //Controller for Contacts view
    var mainControl = can.Control({
        init: function(element, options) 
        {
            Contacts.findAll({},function(data) 
            {
                if (localStorage.getItem("Contacts") != null) 
                {
                    var contactList = JSON.parse(localStorage.getItem("Contacts"));
                    for (var i = 0; i < contactList.length; i++) 
                    {
                        Contacts.contacts.push(contactList[i]);
                    }
                }
                else 
                {
                    Contacts.contacts = data;
                }
                contactsObserver.attr("contacts", Contacts.contacts);
                $('.main').append(can.view('views/main.ejs', Contacts.contacts));
            });
        },

        '.contacts-table td click' : function(el,ev)
        {
            $('.contact-details').html(can.view('views/contact-info.ejs',{el:el},{contactsObserver:contactsObserver}));
            $("#save-edited-contact").hide();
            Contacts.contactdeleted=$(el).attr('value');
        },

        '.add-contact click': function(el, ev) 
        {
            $('.new-contact').html(can.view('views/addContact.ejs', Contacts.contacts));
        },
        '#delete click' : function(el,ev)
        {
            alert("Please select a contact to be deleted");
        }

    });


    //Controller for adding new contacts
    addContactController = can.Control({
        init: function(element, options)
        {
        },
        '.save-contact click': function(el, ev) 
        {

        var newContact={
                // "cname": $('#contact-name').val(),
                "address": $('#address').val(),
                "phoneNo": $('#phone-no').val(),
                "emailId": $('#email').val(),
                "category": $('#categories :selected').text(),
                "dob": $('#dob').val()

        };
        var addContacts = new Contacts();
        //addContacts.newContact=newContact;
        console.log("ADDCONTACTS --->",addContacts);
            addContacts.save(function(result) 
            {
                console.log("RESULT --->",result);
                alert("Contact added successfully");
            });
        }
    });

    //controller for deleting contact
    deleteContactController = can.Control({
        init : function(element,options)
        {

        },
        '#delete-contact click' : function(el,ev)
        {
            var contactdeletion = new Contacts();
            contactdeletion.destroy({id:Contacts.contactdeleted});
            alert("Contact deleted successfully");
        },
        '#edit-contact click' : function(el,ev)
        {
            Contacts.contactedited = $('#ename').text();
            $("#edit-contact").hide();
            $("#delete-contact").hide();
            $("#ename").attr("contenteditable", "true").addClass("edit");
            $("#eaddress").attr("contenteditable", "true").addClass("edit");
            $("#ephoneNo").attr("contenteditable", "true").addClass("edit");
            $("#eemailId").attr("contenteditable", "true").addClass("edit");
            $("#ecategory").html(can.view('views/categoryTemplate.ejs', {}));
            $("#edob").attr("contenteditable", "true").addClass("edit");
            $("#save-edited-contact").show();

        },
        '#save-edited-contact click' : function(el,ev)
        {
            var updateContact = new Contacts({
                "id":Contacts.contactedited,
                "cname": $('#ename').text(),
                "address": $('#eaddress').text(),
                "phoneNo": $('#ephoneNo').text(),
                "emailId": $('#eemailId').text(),
                "category": $('#ecategory :selected').text(),
                "dob": $('#edob').text()
            });
            updateContact.save(function() 
            {
                alert("Contact updated successfully");
            });
        }

    });

    //contoller for categories view
    categoryController = can.Control({
        init: function(element, options) 
        {
            $('.categories').html(can.view('views/categories.ejs', {}));
        },
        '.categories-list td click': function(el, ev) 
        {
            $('.category-members').html(can.view('views/categoryList', 
            {
                el: el
            },
            {
                contactsObserver: contactsObserver
            }));
        }
    });


    //fixtures
    can.fixture("GET /contacts", "json/contacts.json");
    can.fixture("POST /contacts",function(param) {
        console.log("PARAM --->",param);
        // Contacts.contacts.push(param.data);
        //         contactsObserver.attr("contacts", Contacts.contacts);
        //         localStorage.setItem("Contacts", JSON.stringify(Contacts.contacts));
    });
    can.fixture("DELETE /contacts",
    function(){
        for(var i=0,len=Contacts.contacts.length;i<len;i++)
        {
            if(Contacts.contacts[i].cname == Contacts.contactdeleted)
            {
                Contacts.contacts.splice(i,1);
                contactsObserver.attr("contacts",Contacts.contacts);
                localStorage.setItem("Contacts", JSON.stringify(Contacts.contacts));
            }
        }
    });
    can.fixture("PUT /contacts/{id}",function(param){
        console.log("Prat",param);
        for(var i=0,len=Contacts.contacts.length;i<len;i++)
        {
            if(Contacts.contacts[i].cname == Contacts.contactedited)
            {
                Contacts.contacts[i].id = param.data.cname;
                Contacts.contacts[i].cname = param.data.cname;
                Contacts.contacts[i].address = param.data.address;
                Contacts.contacts[i].phoneNo = param.data.phoneNo;
                Contacts.contacts[i].emailId = param.data.emailId;
                Contacts.contacts[i].category = param.data.category;
                Contacts.contacts[i].dob = param.data.dob;
            }
        }
        contactsObserver.attr("contacts",Contacts.contacts);
        localStorage.setItem("Contacts", JSON.stringify(Contacts.contacts));
    });


    new headerControl('.header-section');
    new mainControl('.main-content');
    new addContactController('.new-contact');
    new categoryController('.categories');
    new deleteContactController('.contact-details');
})();

My views are: addContact.ejs

<table class="contact-details">
<tr><td>Name </td><td><input type="text" id="contact-name"/></td></tr>
<tr><td>Address </td><td><input type="textarea" id="address"/></td></tr>
<tr><td>Phone No </td><td><input type="text" id="phone-no"/></td></tr>
<tr><td>Email Id </td><td><input type="text" id="email"/></td></tr>
<tr><td>Category </td><td>
<select id="categories">
    <option value="default">Select Category</option>
    <option value="Friend">Friend</option>
    <option value="Family">Family</option>
    <option value="Home">Home</option>
    <option value="Work">Work</option>
    <option value="Others">Others</option>
</select>
</td></tr>
<tr><td>Date of Birth :</td><td><input type="text" id="dob"/></td></tr>
</table>
<button class="save-contact">Save</button>
<%
$(".new-contact").dialog({height: 500,
            width: 500,
            modal: true,
            position: 'center',
            autoOpen: true,
            title: 'Add a Contact',
            overlay: { opacity: 1.0, background: "black"},
            closeOnEscape: true});
%>

categories.ejs:

<table class="categories-list">
    <tr><th>Categories</th></tr>
    <tr><td value="Friend">Friends</td></tr>
    <tr><td value="Family">Family</td></tr>
    <tr><td value="Home">Home</td></tr>
    <tr><td value="Work">Work</td></tr>
    <tr><td value="Others">Others</td></tr>
</table>

categoryList.ejs:

<table>
    <tr><th><%= el.text()%></th></tr>
    <% var temp = el.attr("value");
    var count = 0;
    var contacts=contactsObserver.attr("contacts");
       for(var i=0,len=contacts.length;i<len;i++){
        if(contacts[i].attr('category') == temp){
    %>
        <tr><td><%= contacts[i].attr('cname')%></td></tr>
    <%}
    else{
        count++;
        }
    }
    if(count == contacts.length){%>
    <tr><td>No Contacts</td></tr>
    <%}%>
</table>

categoryTemplate.ejs

<select id="categories">
    <option value="default">Select Category</option>
    <option value="Friend">Friend</option>
    <option value="Family">Family</option>
    <option value="Home">Home</option>
    <option value="Work">Work</option>
    <option value="Others">Others</option>
</select>

contact-info.ejs:

<table class="contact-detail">
    <% var temp = el.attr("value");
    var count = 0;
    var contacts=contactsObserver.attr("contacts");
       for(var i=0,len=contacts.length;i<len;i++){
        if(contacts[i].attr('cname') == temp){
        console.log("hi");
    %>
        <tr><td>Name</td><td id="ename" contenteditable="false"><%= contacts[i].attr('cname')%></td></tr>
        <tr><td>Address</td><td id="eaddress" contenteditable="false"><%= contacts[i].attr('address')%></td></tr>
        <tr><td>Phone No</td><td id="ephoneNo" contenteditable="false"><%= contacts[i].attr('phoneNo')%></td></tr>
        <tr><td>EmailId</td><td id="eemailId" contenteditable="false"><%= contacts[i].attr('emailId')%></td></tr>
        <tr><td>category</td><td id="ecategory" contenteditable="false"><%= contacts[i].attr('category')%></td></tr>
        <tr><td>Date Of Birth</td><td id="edob" contenteditable="false"><%= contacts[i].attr('dob')%></td></tr>

    <%}}%>
    <tr><td><button id="delete-contact">Delete</button></td></tr>
    <tr><td><button id="edit-contact">Edit</button></td></tr>
    <tr><td><button id="save-edited-contact">Save</button></td></tr>

</table>

<%
$(".contact-details").dialog({height: 300,
            width: 500,
            modal: true,
            position: 'center',
            autoOpen: true,
            title: 'Contact Details',
            overlay: { opacity: 1.0, background: "black"},
            closeOnEscape: true});
%>

header.ejs:

<header>Can-Contacts</header>

main.ejs:

<table class="contacts-table">
<tr><th>Contacts</th></tr>
    <% 
    var contacts=contactsObserver.attr("contacts");
    console.log(contacts);
    contacts.each(function(contact)
    {
    %>
    <tr><td value="<%=contact.attr('cname')%>"><%=contact.attr('cname')%></td></tr>
    <%
    });
    %>
</table>
<button class="add-contact">Add Contact</button>

The problem is "If you click on the add button.The save has to go into post/contacts fixture but It is going to put/contacts/false.

Please help me on this issue

'>' in an attribute causes memory to balloon.

Using a greater than symbol ( > ) in a data-bind attribute caused node's memory usage to balloon upon page refresh, resulting in an out of memory

< input type="submit" name="submitBtn" value="Export" data-bind="enable: shapeIds().length > 0" / >

Express + Vash = Stack Trace

Hi,
Could you add some information which method or property fails when template is rendering. Exception below really useless. The "object is not a function" says about nothing :( If you add names of objects you save my nerves :)

Thanks :)

Express
500 TypeError: object is not a function
at C:\Users\D.PARTNER\projects\srvman\node_modules\vash\build\vash.js:815:13
at Object.vash.loadFile (C:\Users\D.PARTNER\projects\srvman\node_modules\vash\build\vash.js:805:10)
at View.vash.renderFile [as engine] (C:\Users\D.PARTNER\projects\srvman\node_modules\vash\build\vash.js:811:8)
at View.render (C:\Users\D.PARTNER\projects\srvman\node_modules\express\lib\view.js:75:8)
at Function.app.render (C:\Users\D.PARTNER\projects\srvman\node_modules\express\lib\application.js:504:10)
at ServerResponse.res.render (C:\Users\D.PARTNER\projects\srvman\node_modules\express\lib\response.js:753:7)
at Object.exports.render (C:\Users\D.PARTNER\projects\srvman\controllers\rsmodel.js:24:13)
at Promise. (C:\Users\D.PARTNER\projects\srvman\controllers\questions\list.js:55:21)
at Promise. (C:\Users\D.PARTNER\projects\srvman\node_modules\mongoose\node_modules\mpromise\lib\promise.js:162:8)
at Promise.EventEmitter.emit (events.js:95:17)

P.S. Cool template engine.

returning a `Helpers` object breaks $('whatever').html( tpl() ) pattern

Without an explicit toString, it looks like jQuery's .html() doesn't coerce the Helpers context to output properly.

To avoid confusion and breaking existing code, I propose the following:

  • A second parameter to the function returned from vash.link, options. This object is checked for existence and returnContext property within the executing template, compiled template defaults to returning a string.
  • Possibly an option like vash.config.forceReturnString = true[false]. If true, template always returns a string and cannot return a context. Since the overhead of checking for the option isn't really a big deal, this is probably overkill and confusing.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.