Last active
October 25, 2017 16:23
-
-
Save green3g/8770a18b06c04e28ee425a9edccdf3e2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width"> | |
<title>CanJS</title> | |
<style> | |
html, | |
body, | |
#viewDiv { | |
padding: 0; | |
margin: 0; | |
height: 100%; | |
width: 100%; | |
} | |
.top { | |
position:absolute; | |
top:0; | |
left:50%; | |
background:red; | |
color:white; | |
padding:20px; | |
} | |
</style> | |
</head> | |
<body> | |
<body> | |
<div id="viewDiv"></div> | |
</body> | |
<link rel="stylesheet" href="https://js.arcgis.com/4.5/esri/css/main.css"> | |
<script src="https://js.arcgis.com/4.5/"></script> | |
<script src="https://unpkg.com/can/dist/global/can.all.js"></script> | |
<script> | |
require([ | |
"esri/Map", | |
"esri/views/MapView", | |
"dojo/domReady!" | |
], function(Map, MapView) { | |
var map = new Map({ | |
basemap: "gray" | |
}); | |
var view = new MapView({ | |
container: "viewDiv", | |
map: map, | |
zoom: 4, | |
center: [15, 65] // longitude, latitude | |
}); | |
decorate(view); | |
const render = can.stache('<p class="top">Zoom: {{view.zoom}}<br />Timer: {{timer}} </p>'); | |
const scope = new can.DefineMap({ | |
view: view, | |
timer: 0 | |
}); | |
setInterval(function(){ | |
scope.timer = scope.timer +1; | |
}, 2000); | |
document.body.appendChild(render(scope)); | |
}); | |
var canSymbol = can.Symbol, | |
observation = can.Observation; | |
/** | |
* Decorate esri's observable type with canjs methods | |
* @param {esri/core/Accessor} obj the current object being accessed | |
* @param {esri/core/Accessor} parent the root parent accessor object | |
* @param {String} path the path to the value of the object from the parent | |
* @returns {esri/core/Accessor} the decorated object or the value if `obj` is not an object | |
*/ | |
function decorate (obj, parent = null, path = null) { | |
// make sure object exists and isn't already decorated through circular references | |
if (!obj || !obj.__accessor__ || obj[canSymbol.for('can.onKeyValue')]) { | |
return obj; | |
} | |
const handlers = { | |
}; | |
obj[canSymbol.for('can.isMapLike')] = true; | |
// when a value gets unbound, remove its watch handle and the handler | |
obj[canSymbol.for('can.offKeyValue')] = function (key, handle) { | |
if (!handlers[key]) { | |
handlers[key] = []; | |
} | |
const handler = handlers[key]; | |
if (handler) { | |
// remove the handler | |
const index = handler.handlers.indexOf(handle); | |
handler.handlers.splice(index, 1); | |
} | |
// clean up the watch handle if no handlers | |
if (!handler.handlers.length) { | |
handler.watch.remove(); | |
handler.watch = null; | |
} | |
}; | |
// when a value gets bound, register its handler using `watch` | |
obj[canSymbol.for('can.onKeyValue')] = function (key, handler) { | |
console.log(key, handler); | |
if (!handlers[key]) { | |
handlers[key] = { | |
watch: null, | |
handlers: [] | |
}; | |
} | |
// register one single watcher | |
if (!handlers[key].watch) { | |
const watchProp = path ? `${path}.${key}` : key; | |
handlers[key].watch = (parent || obj).watch(watchProp, (newValue, oldValue, propertyName, target) => { | |
handlers[key].handlers.forEach((handle) => { | |
handle(newValue, oldValue); | |
}); | |
}); | |
} | |
// push the handler into the stack | |
handlers[key].handlers.push(handler); | |
}; | |
// when a value is gotten, call observation.add | |
obj[canSymbol.for('can.getKeyValue')] = function (key) { | |
const fullPath = path ? `${path}.${key}` : key; | |
observation.add(obj, key); | |
console.log(obj, key); | |
return fullPath.indexOf('.') > -1 ? get(parent || obj, fullPath) : obj[key]; | |
}; | |
// decorate child keys | |
obj.keys().forEach((key) => { | |
const fullPath = path ? `${path}.${key}` : key; | |
console.log(key); | |
decorate(obj[key], (parent || obj), fullPath); | |
}); | |
return obj; | |
} | |
function get (obj, name) { | |
// The parts of the name we are looking up | |
// `['App','Models','Recipe']` | |
var parts = typeof name !== 'undefined' ? (String(name)).replace(/\[/g, '.') | |
.replace(/]/g, '').split('.') : [], | |
length = parts.length, | |
current, i, container; | |
if (!length) { | |
return obj; | |
} | |
current = obj; | |
// Walk current to the 2nd to last object or until there | |
// is not a container. | |
for (i = 0; i < length && isContainer(current); i++) { | |
container = current; | |
const key = parts[i]; | |
observation.add(obj, key); | |
current = container[key]; | |
} | |
return current; | |
} | |
function isContainer(current) { | |
return /^f|^o/.test(typeof current); | |
} | |
</script> | |
</body> | |
</html> | |
<html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment