kirbysayshi / vash Goto Github PK
View Code? Open in Web Editor NEWVash, the 60 billion double-dollar template-maker. Razor syntax, for JavaScript templates
License: Other
Vash, the 60 billion double-dollar template-maker. Razor syntax, for JavaScript templates
License: Other
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?
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)?
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?
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
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
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.
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:
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 |
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.
https://github.com/kirbysayshi/vash/blob/master/src/vruntime.js#L9
why there are an extra call into define()
, it seems this one confuses r.js, and as a consequence, the correct module path won't be added to the generated.js
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:
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.
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 require
ing 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.
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.
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.
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.
-nevermind please close-
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.
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:
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:
parentContext
that can be passed in manually (or just "another context")Helpers
instanceHelpers
instance instead of the rendered stringI 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!
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
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
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 ?
If an error is encountered when eval
ing 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.
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:
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?
Can't use i18n functions in vash view just like that:
@__("i18n_key")
Any workarounds?
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
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.
Git remotes/clones will need to be updated. This can be done via the git remote set-url command:
git remote set-url origin [email protected]:[YOURUSERNAME]/vash.git
I did this because urls are less surprising when they're lowercase.
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>
See https://github.com/kirbysayshi/Vash/blob/master/src/vhelpers.layout.js#L70
'Extends' is a reserved keyword. Internet Explorer fails to parse the script, raising a SyntaxError.
Using vash with Docpad, if I save a file with "normal" line endings in Visual Studio, vash will not process the template at all. It outputs the template unmodified.
When topnavbar.vash file is a UTF8 file with signature, then @html.include('topnavbar',model) will include the UTF8 Byte order mark (0xEF,0xBB,0xBF)
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.
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?
These directories are not anymore included in the latest 1237 (https://registry.npmjs.org/vash), which of course causes node.js to fail on require("vash").
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 :)
Error:
UnmatchedCharacterError: Unmatched BRACE_OPEN at line 1, character 1. Value: {
+PROGRAM
| +BLOCK
| -BLOCK
-PROGRAM
Source:
@{
{
<b data></b>
}
<img />
}
May be related to #26
Interestingly, the attribute & the /
in the self-closing tag are both necessary to reproduce the bug. Adding an @
to the inner block does not help.
This worked in [email protected], and fails in [email protected]
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)
@{ var myMessage = "Tweet me! @Schabse"; }
Vash parses the @
as an interpolation and breaks.
@
s should be ignored inside string literals.
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?
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!
Hi kirbysayshi ,
I have a little problem. Why I can't use variable into attribute?
For example, this code always fails https://gist.github.com/gr1feel/5418010
So that the header text is visible when clicking the TOC link. :)
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?
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.
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)
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;
});
}
I get the following error....
500 RangeError: Problem while rendering template at line 23, character 1.
Original message: Maximum call stack size exceeded
https://www.dropbox.com/s/zsfgw7oydcrau9u/Screenshot%202014-02-28%2017.16.56.png
...when this simple view file that uses a layout loops through too many items.
View file:
https://gist.github.com/crdeutsch/9283351
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 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
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" / >
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.
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:
vash.link
, options
. This object is checked for existence and returnContext
property within the executing template, compiled template defaults to returning a string.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.A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.