I have a view setup that has a canvas and several inputs in it.
I am calling an action in the view when a button is pressed and I need to access the canvas and input's.
Obviously I could use something like what I have below but if I have more than 1 of these view's on a page then getting an element via ID just isn't going to cut it.
var canvas = document.getElementById("canvasThumbResult");
I have the canvas setup like this in the view's template
<canvas id="canvasThumbResult" width="128" height="128"></canvas>
Is there a good way to get an element from an action in Ember or is there a way I can search for the element only inside the current view's output?
you can access any HTML Element within your Ember.View with this.$(/*jquery identifier*/) so, for an example you can access your canvas like
var App.MyCanvasView = Ember.View.extend({
actions: {
myAction: function () {
console.log(this.$('#canvasThumbResult'));
}
}
});
Related
I'm working on implementing a QR reader in a web based app that uses the PC's webcam. This is currently working correct.
The framework that I use (barcode.js) has a function render(element).
I have 2 different files, ScannerView.html and ScannerView.js. See their code below:
ScannerView.html
<!-- Content Header (Page header) -->
<section class="content-header has-background-image">
<div class="background">
<img src="/assets/temp/header.png" />
</div>
<h1><div class="icon"><i class="fa fa-wrench"></i></div> <%=name%></h1>
</section>
<section class="content">
// Withing the following div, the canvas element should be placed
<div id="scanner"></div>
</section>
ScannerView.js
var YookrApp = require("../../setup");
var scanner = null;
var ScannerView = Backbone.Marionette.CompositeView.extend({
template: require("./ScannerView.html"),
className: "scannerView",
ui: {
scannerDiv: "#scanner"
},
name: "Yookr Code Scanner",
initialize: function(options) {
},
onRender: function() {
w69b.qr.decoding.setWorkerUrl("assets/w69b.qrcode.decodeworker.js");
scanner = new w69b.qr.ui.ContinuousScanner();
// Called when a qr code has been decoded.
scanner.setDecodedCallback(function(result) {
console.log("Decoded qr code:", result);
});
scanner.setStopped(false);
// Render component in element with id "scanner".
console.log("Start rendering");
scanner.render(this.ui.scannerDiv);
console.log("Rendering done");
},
close: function() {
// We have to dispose the scanner object.
// If we don"t do this, the webcam will
// always be enabled
scanner.dispose();
}
});
module.exports = ScannerView;
When I run my app, the scanner.render() function should add a <canvas> element inside <div id="scanner"></div> in ScannerView.html
Problem
I'm not able to render the canvas using scanner.render() properly withing the <div id="scanner"></div> that is located in my html file. I tried to use document.getElementById and this.ui.scannerDiv with different, but not correct result.
Because I defined an UI element in the ScannerView.js file, I should be able to call scanner.render(this.ui.scannerDiv); This should use the div with id scanner in my html view, but instead the canvas is not rendered at all. In my console, I can see the following warnings:
[.Offscreen-For-WebGL-0000020AB57365B0]GL ERROR :GL_INVALID_FRAMEBUFFER_OPERATION : glDrawArrays: framebuffer incomplete
and
[.Offscreen-For-WebGL-0000020AB57365B0]RENDER WARNING: texture bound to texture unit 2 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering.
When I use scanner.render(document.getElementById("scanner"));, I can see that the canvas is rendered, but not in the correct location. Please see my added screenshot for the result:
At this point I'm stuck. I dont know how I can achieve that the canvas is rendered in the correct div.
After searching Google for a while longer, I found a solution.
The onRender: function() { } "gets triggered when the View's DOM subtree is prepared for insertion into the DOM but before those elements are viewable", according to this webiste.
after changing onRender to onShow in my javascript file, the canvas element is rendered in the correct location.
How can I initialize a variable in JavaScript with a direct HTML code?
I am trying to put an animate tag in a variable so that I can append to the svg whenever a mouseover event occurs. I am using snap.svg.
var g = HTML CODE
var s = Snap("#svg");
s.mouseover(function(){
s.append(g);
});
Something like that. I know this syntax is wrong. I didn't want to write this tag in my html code but keep it hidden and then append it
Probably the easiest way:
var someHTML = '<div>Heeeyy</div>',
someElem = document.getElementById('someElement');
someElem.onmouseover = function(){
someElem.insertAdjacentHTML('beforeend', someHTML );
someElem.onmouseover = null; // Remove this if you want it to happen on every mouseover event
}
Alternatively, you can create a new element with document.createElement('DIV') and set the innerHTML to the desired html. Then append the created element with appendChild on the parent (desired element).
animateTransform doesn't have good support on some browsers like IE, so I tend to stay away from using that method, if something like Snap is available. If it is, I would do something similar to the following...
s = Snap(400, 620);
var c = s.circle(10,10,10);
var myMarkup = '<g><rect x="20" y="20" width="100" height="100"></g>'
c.mouseover( function() {
s.append( Snap.parse( myMarkup ) )
s.select('g').animate({ transform: 't50,50' }, 3000)
})
jsfiddle (hover over circle)
If you were just doing the markup to add an animateTransform element, you can skip the parsing/appending stuff as well, as thats not needed.
Good Afternoon everyone.
I'm trying to color the comment item when I go to the page with the comment included through notifications. - Like fb or stack overflow.
I have everything working except the part that I mentioned above.
Notification Events
Template.notification.events({
'click a':function() {
var commentTemplate = this.commentId;
console.log(commentTemplate); //Target commentId returns successfully
//Code here needed
//to color comment when page moves to
//coresponding page.
}
Template.commentList
//HTML
{{#each comments}}
{{> commentItem}}
{{/each}}
//JS
comments: function(){
return Comments.find({postId:this._id});
}
I've also tried grabbing the corresponding commentItem's id through console.log using this._id.
So What I would like to know is,
is there a way to link this.commentId from notifications and access <template name = "commentItem"> with corresponding _id. And then manipulate it's element / dom by using things such as .addClass.
Please nudge me in the right direction!
If I understand you correctly, when you click a link in the notifications template, you want to take the user to the commentList page and then manipulate the CSS of the referred-to comment? There are probably a couple of ways to do this.
The first step is going to be to make sure that you have a way to select that particular DOM element once the page loads. For that, in your commentItem template, you might do something like this:
<template name='commentItem'>
<div class='commentItem' id='comment-{{_id}}'>
....
</div>
</template>
If you're using iron:router, a quick and easy way (but not a particularly robust way) to do this would be to manually redirect to the commentList page, then perform your manipulation as part of the event handler once the page has rendered:
Template.notification.events({
'click a':function(event) {
event.preventDefault(); // don't let this take you anywhere
var commentTemplate = this.commentId;
Router.go($(event.currentTarget).attr('href'));
setTimeout(function() {
$('#comment-' + commentTemplate).addClass('whatever-class-you-want');
}, 500); // need to wait for the page to render first -- this is probably not a robust method
}
});
A more robust option, which has the added benefit of persisting on page refresh, might be to add an optional referrer parameter to the URL (i.e., have the link be something like ..., where [comment _id] is replaced by the _id of the comment in question), then in your commentList template, once your page has rendered, you can see if there's a referrer, and if there is, change the CSS:
Template.commentList.rendered = function() {
var referrer = Router.current().params.query.referrer;
if (referrer) {
$('#comment-' + referrer).addClass('whatever-class-you-want');
}
}
i have this code which is suppose to get array values from iframe to the parent window
$("#close_nr").bind("click", {page: this}, function (e) {
var chkroomArr = new Array();
$("input[name='name'].checked").each(function () {
chkroomArr.push($(this).val());
chkroomArr.toString();
$("#RoomCategoryID", window.parent.document).val(chkroomArr);
});
$(".yui3-button-close", parent.document).trigger("click");
$(".yui3-panel-content", parent.document).remove();
});
how can i do this code to work because it is not passing the require value to the parent window. and how can i get the value to display went it is in the parent window
thanks in advance
Create a function in parent - window and call them instead of set value. E.g:
in parent window:
function SetValue(valToSet) {
$("#RoomCategoryID").val(valToSet);
}
in "click" - event call
window.parent.SetValue(chkroomArr);
instead of
$("#RoomCategoryID", window.parent.document).val(chkroomArr);
EDIT:
For $(".yui3-button-close", parent.document).trigger("click");
$(".yui3-panel-content", parent.document).remove();
also is better to create a function in parent - window and call it.
You can refer to this question: Better way to pass many form input values from child to parent window
if the URL of the iframe src is not in the same domain as the parent, there could be cross-domain security issues that prevent manipulation via javascript, as per the same-origin policies.
I recently started to develop a class that manipulates over CodeMirror - dynamically links necessary libraries, provides comunication with server and so on.
Because of that I hold everything in variables, and upon initialisation, the CodeMirror is appended to DOM node which is not within document tree. Just like that:
var holder = document.createElement("div");
var textarea = document.createElement("textarea");
holder.appendChild(textarea);
this.editor = CodeMirror.fromTextArea(textarea, {/*options*/});
Then I append the DIV myself when .show() method is called upon my class:
this.show(node) {
if(this.editor!=null) {
node.parentNode.replaceChild(holder,node);
}
}
The editor is OK since click into it and try to draw, or after I resize window. But before, I just see blank area with disabled scroll bar. I believe this is because of way I initialise whole CodeMirror.
So what should I do to make it work, if I want to keep my class structure?
Link to live code (not for IE).
A more direct way would be to call .refresh() on the CodeMirror instance after showing it. See http://codemirror.net/doc/manual.html#refresh
So I solved the issue very simply - I dispatch onresize event after adding editor to dom tree:
node.parentNode.replaceChild(holder,node);
var evt = document.createEvent('UIEvents');
evt.initUIEvent('resize', true, false,window,0);
window.dispatchEvent(evt);
Based on How to dispatch resize event? question.