Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

can.view.href #1641

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions view/doc/elements_and_attributes.md
Expand Up @@ -24,6 +24,8 @@ The following is supported by CanJS's [can.mustache] and [can.stache] templates
<input can-value="{name}"/>
```

- [can.view.href] - Sets an element's href attribute so that it's url will set the specified attribute values on [can.route].

## Plugins

The following functionality is available within plugins:
Expand Down
49 changes: 49 additions & 0 deletions view/href/href.js
@@ -0,0 +1,49 @@
steal("can/util",
"can/view/stache/mustache_core.js",
"can/view/callbacks",
"can/view/scope", function (can, mustacheCore) {


var removeCurly = function(value){
if(value[0] === "{" && value[value.length-1] === "}") {
return value.substr(1, value.length - 2);
}
return value;
};

// registers a callback can-href
can.view.attr("can-href", function(el, attrData){

// foo='bar' zed=5 abc=myValue
// Note: 'tmp ' is added because expressionData "Breaks up the name and arguments of a mustache expression.", but we don't use name:
var attrInfo = mustacheCore.expressionData('tmp ' + removeCurly(el.getAttribute("can-href")));
// -> {hash: {foo: 'bar', zed: 5, abc: {get: 'myValue'}}}

var routeHref = can.compute(function(){
var hash = {};
can.each(attrInfo.hash, function(val, key) {
if (val && val.hasOwnProperty("get")) {
hash[key] = attrData.scope.read(val.get, {}).value;
} else {
hash[key] = val;
}
});
return can.route.url(hash);
});


el.setAttribute("href", routeHref());

var handler = function(ev, newVal){
el.setAttribute("href", newVal);
};

routeHref.bind("change", handler );

can.bind.call(el,"removed", function(){
routeHref.unbind("change", handler );
});
});


});
55 changes: 55 additions & 0 deletions view/href/href.md
@@ -0,0 +1,55 @@
@page can.view.href
@parent can.view.bindings

Sets an element's href attribute so that it's url will set the specified attribute values on [can.route].

@siganture `can-href='{[attrName=attrValue...]}'`

@param {String} attrName
@param {can.stache.key} attrValue

@body

## Use

With no pretty routing rules, the following:

```
<li><a can-href='{page="recipe" id=5}'>{{recipe.name}}</a></li>
```

produces:

```
<li><a href='#!&page=5&id=5'>{{recipe.name}}</a></li>
```

If pretty route is defined like:

```
can.route(":page/:id")
```

The previous use of `can-href` will instead produce:

```
<li><a href='#!page/5'>{{recipe.name}}</a></li>
```

You can use values from stache's scope like:

```
<li><a can-href='{page="recipe" id=recipeId}'>{{recipe.name}}</a></li>
```

If `recipeId` was 6:

```
<li><a href='#!page/6'>{{recipe.name}}</a></li>
```

If `recipeId` is observable and changes to 7:

```
<li><a href='#!page/7'>{{recipe.name}}</a></li>
```
52 changes: 52 additions & 0 deletions view/href/href_test.js
@@ -0,0 +1,52 @@
steal("can/test", "steal-qunit", "can/route", function () {

var makeIframe = function(src){
var iframe = document.createElement('iframe');
window.removeMyself = function(){
delete window.removeMyself;
delete window.isReady;
delete window.hasError;
document.body.removeChild(iframe);
start();
};
window.hasError = function(error) {
ok(false, error.message);
window.removeMyself();
};
window.isReady = function(el, viewModel, setPrettyUrl) {

equal(el.find('a').attr('href'), "#!&page=recipe&id=5", "should set unpretty href attribute");

viewModel.recipe.attr('id', 7);
equal(el.find('a').attr('href'), "#!&page=recipe&id=7", "should update href");

setPrettyUrl();
viewModel.recipe.attr('id', 8);
equal(el.find('a').attr('href'), "#!recipe/8", "should set pretty href");

viewModel.recipe.attr('id', 9);
equal(el.find('a').attr('href'), "#!recipe/9", "should update pretty href");

window.removeMyself();
};
document.body.appendChild(iframe);
iframe.src = src;
};

QUnit.module("can/view/href");
if(window.steal) {
asyncTest("the basics are able to work for steal", function(){
makeIframe( can.test.path("view/href/tests/steal-basics.html?"+Math.random()) );
});
}
//else if(window.requirejs) {
// asyncTest("the basics are able to work for requirejs", function(){
// makeIframe(can.test.path("../../view/href/tests/requirejs-basics.html?"+Math.random()));
// });
//} else {
// asyncTest("the basics are able to work standalone", function(){
// makeIframe(can.test.path("view/href/tests/standalone-basics.html?"+Math.random()));
// });
//}

});
3 changes: 3 additions & 0 deletions view/href/test.html
@@ -0,0 +1,3 @@
<title>can/view/href</title>
<script src="../../node_modules/steal/steal.js" main="can/view/href/href_test"></script>
<div id="qunit-fixture"></div>
27 changes: 27 additions & 0 deletions view/href/tests/steal-basics.html
@@ -0,0 +1,27 @@
<script>
window.isReady = window.parent.isReady || function(el) {
console.log(el.length);
console.log(el.html());
};
window.hasError = window.parent.hasError || function(error) {
console.log("error in autoload", error)
};
window.removeMyself = window.parent.removeMyself;
</script>
<script type="text/stache" id="basics">
<a can-href="{page='recipe' id=recipe.id}">{{recipe.name}}</a>
</script>
<script src='../../../node_modules/steal/steal.js' main='can/view/href/'></script>


<script>
steal('can', 'can/view/href', 'can/view/href/tests/steal-basics.js', function(can){
console.log();
$("body").html(can.view.mustache('<href-component>Test component</href-component>'));
isReady($("body href-component"), can.viewModel('href-component'), function(){
can.route(":page/:id");
});
});
</script>


17 changes: 17 additions & 0 deletions view/href/tests/steal-basics.js
@@ -0,0 +1,17 @@
steal("can/component", "can/util",function(Component, can){
return Component.extend({
tag: "href-component",
template: $('#basics').html(),
viewModel: {
recipe: {
id: 5,
name: 'Cool recipe'
}
},
events: {
"inserted": function(){
console.log('href-component INSERTED');
}
}
});
});