Adapting JavaScript into Polymer - javascript

IGNORE THIS PART EDIT 4 IS THE MOST PERTINENT (see below)
loving Polymer! Just trying to adapt three functions into my code:
Polymer('my-element', {
// JavaScript for Box (Also Beta)
unhidePanel: function(panelName) {
var panel = this.$.panelName;
var hidden = panel.getAttribute('isPanelHidden');
if (hidden == "true") {
panel.style.display="block";
panel.setAttribute('isPanelHidden', "false");
}
else {
panel.style.display="none";
panel.setAttribute('isPanelHidden', "true");
}
},
voteDefPercent: function(val,defid) {
var def = this.$.defid;
var upvotes = parseInt(def.getAttribute("data-upvotes"),10) + val;
var votes = parseInt(def.getAttribute("data-votes"),10) + 1;
var percent = Math.round((upvotes / votes) * 100);
def.setAttribute('data-upvotes', upvotes);
def.setAttribute('data-votes', votes);
def.value = percent;
},
voteidPercent: function(val,tagid) {
var tag = this.$.tagid;
var upvotes = parseInt(tag.getAttribute("data-upvotes"),10) + val;
var votes = parseInt(tag.getAttribute("data-votes"),10) + 1;
var percent = Math.round((upvotes / votes) * 100);
tag.style.backgroundSize = percent + "%, 100%, 100%, 100%";
tag.setAttribute('data-upvotes', upvotes);
tag.setAttribute('data-votes', votes);
},
// End JavaScript
});
These functions were originally JavaScript, with a couple changes. The code isn't working for any of the three so I'm wondering if there is a syntax problem or some other thing I need to change. Is it possible to pass variables using the form onclick: {{ functionName(variableName) }} or is there some sort of other special syntax? Thanks so much!!
EDIT 1
Example of HTML code:
<button type="button" class="btn btn-default tag-upvote" on-click="voteidPercent(1,'sample-tag-1')"></button>
<button type="button" class="btn btn-default tag-link" id="sample-tag-1" data-upvotes="0" data-votes="0">Official Symbol</button>
<button type="button" class="btn btn-default tag-downvote" on-click="voteidPercent(0,'sample-tag-1')"></button>
EDIT 2
The system has three generic functions which are called many times by many different components. I have a feeling getting just one of them working will help me determine on my own how to fix the rest.
The HTML shown in EDIT 1 describes a group of buttons. Only the center button is visible unless the user hovers over it, splitting it into three buttons.
The three buttons are: (Upvote Button)(Link Button)(Downvote Button)
Depending on the percentage of "upvotes" vs. "total votes", when the user is no longer hovering over the button, the original center button is the only one remaining, but the percentage red or green changes depending on the percentage of upvotes vs. total votes.
There are about 50 - 80 of these button groups per page so passing each as an individual function is a tad cumbersome, but each has an individual value.
In order to store/calculate the percentage, the center button has two attributes "data-upvotes" and "data-votes". Further, whenever the upvote button is pressed it passes a parameter 1 (to add to the upvote count) and the name of the center button, whereas the downvote button passes a 0 (to add to the upvote count) and the name of the center button.
I can't think of an efficient way to do this without parameters and desperately need some pointing in the right direction. Thank you so much and thanks to Dirk for his help getting this far!
EDIT 3
I've given this a few days and I'm still lost. My current HTML example is as follows:
<p><button type="button" class="btn btn-default btn-circle" isPanelHidden="true" on-tap="{{ unhidePanel }}" panelName="relational-tags-area-1"><span class="glyphicon glyphicon-play" id="category-button"></span></button></p>
And then my refined JavaScript:
unhidePanel: function() {
var panelName = this.$.getAttribute('panelName');
var hidden = panel.getAttribute('isPanelHidden');
console.log(panelName);
if (hidden == "true") {
panel.style.display="block";
panel.setAttribute('isPanelHidden', "false");
}
else {
panel.style.display="none";
panel.setAttribute('isPanelHidden', "true");
}
},
I'm getting an "Uncaught Type error: undefined is not a function" at var panelName = this.$.getAttribute('panelName');
EDIT 4
Ignoring everything I've done above, I've run into a larger issue of the same type. Is there any way at all to use JavaScript within a Polymer element? Can I do anything along these lines:
<script language="javascript" type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js">
$(function() {
var sys = arbor.ParticleSystem(1000, 400, 1);
sys.parameters({gravity:true});
sys.renderer = Renderer("#viewport");
var animals = sys.addNode('Animals',{'color':'red','shape':'dot','label':'Animals'});
});
</script>
(This uses arbor.js, which was declared above this statement)
If not, is there a quick fix or work around that won't require rewriting all of my code? Thanks so much, sorry for the trouble.

If 'not working' means that your functions are not called, then indeed it's because your event declarations are wrong (you should have posted the HTML code instead).
You cannot pass parameters to the event handlers
The event attribute is named on-click
So you need to write on-click="{{functionName}}". Please refer to the delcarative event mapping section in the Polymer documentation.

Related

Can bPopup trigger and target divs be assigned dynamically?

We have a list of paired divs dynamically built in a ColdFusion page (internshipHandleX, internshipHiddenX, etc.) by looping over a query and adding the current row, eg:
<div id="internshipHidden#internship.currentrow#" class="hidden pop-up">
that we want to bind together as modal windows and corresponding triggers. Using this code:
for (var row = 1; row <= totalInternships; row ++){
var thisHandle = "#internshipHandle" + row;
var thisHidden = "#internshipHidden" + row;
$(thisHandle).click(function(e){
e.preventDefault();
$(thisHidden).bPopup({modalColor:"black"});
});
}
We apparently link all of the internshipHandle(s) to the last internshipHidden.
What am I missing? Is there a better way to make modal windows out of dynamically created css-hidden divs (that is, within the skeleton framework? I REALLY don't want to start over using bs.)
DreamWeaver is not happy about me putting functions in loops but all the cool kids tell me not to listen to it.
Edit:tryed the same thing with the jqueryUI dialog and had the same problems. I'd love an explanation. Thanks!
Welcome to Javascript. You just encountered a closure in its natural habitat.
In order to have the row variable working the way you expect it to, you need to pass it in its own scope. This can be done using a closure. You may want to dig deeper into that topic, but for now, here is a fix for your problem:
var totalInternships = 2;
for (var row = 1; row <= totalInternships; row++){
var bindInternship = function(rowIndex) {
$("#internshipHandle" + rowIndex).click(function(e){
e.preventDefault();
alert('pop-up #' + rowIndex);
//$("#internshipHidden" + rowIndex).bPopup({modalColor:"black"});
});
};
bindInternship(row);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button type="button" id="internshipHandle1">pop-up 1</button>
<div id="internshipHidden1" class="hidden pop-up">
<button type="button" id="internshipHandle2">pop-up 2</button>
<div id="internshipHidden2" class="hidden pop-up">
Note: I commented the line for the bPopup. Uncomment it, remove the alert and you're good to go.

How to pull css attributes from

I'm trying to figure out how to pull attributes from CSS to be used in Javascript. I've googled what I'm looking for so many times and in so many ways my fingers are about to fall off.
I'm looking to change font size to three different font sizes: 15px, 28px, and 40px. This would be toggled using three buttons. However, when you choose a font size, some of the other CSS attributes need to change in order to resize the text and padding to align with the element "behind" it, so that it doesn't push off the side and look ugly. I'm planning on doing the resizing automatically with Javascript, but for the life of me I can't figure out how to pull the "text size in pixels" attribute from the page in order to apply an "if/else" argument. This would need to be done in browser and I've found a .getComputedStyle command. But as I can't get it to work I'm not sure if that's what I need or not.
<body>
<p id="spaz">Text to be resized.</p>
<button type="button" onclick="txtszl()">large</button>
<button type="button" onclick="txtszm()">medium</button>
<script>
function txtszl(){
document.getElementById("spaz").style.fontSize="40px";
}
function txtszm(){
document.getElementById("spaz").style.fontSize="28px";
}
var $txtelement = document.getElementById("spaz");
var $txtsize = $txtelement.getComputedStyle("fontSize");
if ($txtsize == 40px){
alert("It's forty!");
}else{
alert("Nope!");
}
</script>
</body>
That's what I have come up with. Any help/links would be greatly appreciated!
The getComputedStyle function returns a CSSStyleDeclaration.
var txtElementStyles = getComputedStyle($txtelement, null),
fontSize = txtElementStyles.getPropertyValue('font-size');
Working fiddle: http://jsfiddle.net/wrathchild77/6LJaM/
function txtszl() {
document.getElementById("spaz").style.fontSize = "40px";
check();
}
function txtszm() {
document.getElementById("spaz").style.fontSize = "28px";
check();
}
function check() {
var $txtsize = document.getElementById("spaz").style.fontSize;
if ($txtsize == "40px") {
alert("It's forty!");
} else {
alert("Nope!");
}
}

Optimizing code to define variables only once, code only works when the vars are in change function and for the code outside change I redefine?

Pretty sure I know the solution... would write .on('change','load', function(){}
correct? <-- Tested didn't work? so I am up to your solutions :)
Sushanth -- && adeneo both came up with great solutions, this is a good lesson in optimizing code... It's gonna be hard to choose which answer to go with, but I know this is going to help me rethink how I write... I dont know what I do without this forum, id have to learn this stuff in college.
This is purely a question out of curiosity and bettering my skills, as well as giving you guys a chance to display your knowledge on jQuery. Also to prevent any sloppy writing.
I have a radio based switch box, the markup looks like this, the id's and on/off values are generated by the values in my array with PHP...
<span class="toggle-bg">//This color is the background of the toggle, I need jQuery to change this color based on the state on/off
<input type="radio" value="on" id="_moon_page_header_area1" name="_moon_page_header_area">//this is my on value generated by the array
<input type="hidden" value="_moon_page_header_area" class="switch-id-value">// I create this input because I have multiple checkboxes that have the ID _moon_ARRAYVALUE_area1
<input type="radio" value="off" id="_moon_page_header_area2" name="_moon_page_header_area">// off value
<input type="hidden" value="_moon_page_header_area" class="switch-id-value">//_moon_ARRAYVALUE_area2
<span class="switch"></span>// the switch button that changes
</span>
Hope that makes sense and the comments are clear
Here is the jQuery
var value = $('.toggle-bg input.switch-id-value').val()
var moon1 = $('#'+value+'1').is(':checked');
var moon2 = $('#'+value+'2').is(':checked');
var static_slide = $('._moon_staticarea_height');
var toggle = $('.toggle-bg');
if(moon1){
toggle.css({'background-color': '#46b692'});
static_slide.hide()
} else
if (moon2){
toggle.css({'background-color': '#333'});
static_slide.show()
}
$('.toggle-bg').change(function () {
var value = $('.toggle-bg input.switch-id-value').val()
var moon1 = $('#'+value+'1').is(':checked');
var moon2 = $('#'+value+'2').is(':checked');
var static_slide = $('._moon_staticarea_height');
var toggle = $('.toggle-bg');
if(moon1){
toggle.css({'background-color': '#46b692'});
static_slide.slideUp()
} else
if (moon2){
toggle.css({'background-color': '#333'});
static_slide.slideDown()
}
});
it looks longer than it really is, its just repeating it self, one is on load so that it gives the correct color on load of the page, and then inside the change function we need to change colors..
How do I write it so I only have to use variables one time (so its cleaner) is there a better way to optimize it... Just NOW thinking after writing this I could put it in one function .on('load', 'change', function() {}
I just now thought of that, but I wrote all this so I am going to see what others think...
You'd do that by having the function in the change event handler, and on the end you chain on a trigger('change') to make it work on pageload :
$('.toggle-bg').on('change', function () {
var value = $('.toggle-bg input.switch-id-value').val(),
moon1 = $('#' + value + '1').is(':checked'),
slider = $('._moon_staticarea_height'),
toggle = $('.toggle-bg');
toggle.css('background-color', (moon1 ? '#46b692' : '#333'));
slider[moon1?'slideUp':'slideDown']();
}).trigger('change');
As radiobuttons can't be unchecked, it's either moon1 or moon2, which means checking one of them should be enough.
.on('change','load',
supposed to be
// Remove the comma separator if you want to bind the same handler to
// multiple events.
.on('change load',
And you can remove the one separately written out and enclose it in a function (if multiple instances of the class toggle-bg)
or just trigger the change event.(If there is a single instance of a class)
This will just run the same functionality when the page loads.
var toggle = $('.toggle-bg');
toggle.change(function () {
var value = $('input.switch-id-value', this).val(),
moon1 = $('#' + value + '1').is(':checked'),
moon2 = $('#' + value + '2').is(':checked'),
static_slide = $('._moon_staticarea_height');
if (moon1) {
toggle.css({
'background-color': '#46b692'
});
static_slide.slideUp()
} else if (moon2) {
toggle.css({
'background-color': '#333'
});
static_slide.slideDown()
}
}).change();

Can't get sessionStorage to work correctly

I have multiple buttons that when they are clicked an image is loaded and the image is supposed to stay there based even when the page refreshes. When I use this the button with the highest setItem value always shows even if I click on other button. How do I fix this?
here is one of the scripts:
<script type="text/javascript">
var isImage1 = sessionStorage.getItem('2');
function showImage1() {
sessionStorage.setItem('isImage1', '2');
$("#loadingImage1").show();
$("#loadingImage").hide();
$("#loadingImage2").hide();
$("#loadingImage3").hide();
$("#loadingImage4").hide();
$("#loadingImage5").hide();
$("#loadingImage6").hide();
}
if(isImage1 == 2) showImage1();
</script>
and here is one of my buttons:
<input name="EPL/MECH DESIGN - TECHS" style="white-space:normal"
onclick="moveText(this.name);showImage1();form1.submit()"
style="width: 275px" type="button" value="7SBD EPL/Mech. Design Techs" />
Update: I have updated this line
var isImage1 = sessionStorage.getItem('2');
to
var isImage1 = sessionStorage.getItem('isIamge1');
but my issue still exists, that the isImage with the largest value stays even when i click the other buttons, so help is still needed.
In your session storage, you are setting the value of the 'isImage1' Item to '2'
sessionStorage.setItem('isImage1', '2');
But in your code to retrieve the value you are actually retrieving the item '2'
var isImage1 = sessionStorage.getItem('2');
You need to change your sessionStorage.getItem to reference 'isImage1'
var isImage1 = sessionStorage.getItem('isImage1');
Then you should get the value you are expecting.
There are loads of good jsfiddles on session storage. you may get some ideas from this one:
http://jsfiddle.net/gabrieleromanato/XLRAH/
Incidently; this is a very small value you are storing, why not store it in a cookie instead?
EDIT:
based on the fact that you have multiple functions exactly like this one, you are better off following Ken's solution, the only thing I would add is a wildcard to turn off the other images:
function showImage(imgNum) {
sessionStorage.setItem('Image',imgNum);
$("[id^=loadingImage]").hide();
$("#loadingImage" + imgNum).show();
}
showImage(sessionStorage.getItem('Image'));
The code in the buttons would then be showImage(1) instead of showImage1();
_Pez
By re-factoring the code a little you can do something like this:
/// setup some vars including max number of images
var maxImages = 6, i = 1, v;
/// now loop through and get the items for each image
for(; i =< maxImages; i++) {
v = sessionStorage.getItem('isImage' + i);
/// if in storage, call show image with the number to show
if (v !== null) showImage(i);
}
/// show image based on number
function showImage(num) {
sessionStorage.setItem('isImage' + num, '1');
$("#loadingImage" + num).show();
}
Also note that sessionStorage only deals with strings. So in order to check a specific number you need to convert it to one first parseInt(value, 10);.
But in this case the 1 that we set can be anything - it's just to store some value so sessionStorage doesn't return null.
In the button code you can change it to do this:
<input name="EPL/MECH DESIGN - TECHS" style="white-space:normal"
onclick="moveText(this.name);showImage(1);form1.submit()"
style="width: 275px" type="button" value="7SBD EPL/Mech. Design Techs" />

javascript for the variant of calculator

I am working on the project to create one variant of calculator. Basically, I am storing all the user clicks (which may be number and operator like +,-) in an array and handing the array to the another function when user clicks "=". I am using javascript for this. The below is my code:
var arr=[]; //array of every input from the user interface stored
var i=0; //number of input clicks from the user
var opPos=[]; //position of the operator as given by the user
var operAnd=[];//operands as given by the user
var disp='';
function clearval() {
// This function clears all the values stored in related array when C or CE is pressed
document.getElementById("op").value=0;
arr=[];
i=0;
opPos=[];
operAnd=[];
disp='';
}
//This Function get the value and supplies the array to calculating function
function getval(inp){
if(inp!="=")
{
arr[i]=inp;
disp=disp+inp;//for display in the screen of the output screen
document.getElementById("op").value=disp;
if (typeof inp!="number"){
opPos.push(i);
operAnd.push(inp);
}
i++;
}
else
{
var newInput=assembler(arr,opPos,operAnd);
clearval();
getval(parseFloat(newInput,10));
}
}
//<!------This Function calculates based on array, operator position and operands------!>
function assembler(num_array,opPos,operAnd){
var num='';
var numCollect=[];
var posCount=0;
for(var j=0;j<num_array.length;j++){
if (j==opPos[posCount]) {
numCollect.push(parseFloat(num,10));
num='';
j++;
posCount++;
}
else if (j>posCount) {
}
num=num+num_array[j];
}
num=parseFloat(num,10);
numCollect.push(num);
//document.getElementById("op").value= numCollect;
var newInput=calculator(numCollect,operAnd);
return newInput;
}
function calculator(target_num,operAnd) {
// Not the nice solution but straightforward nonetheless
var result='';
for (var l=0;l<operAnd.length;l++) {
result=result+target_num[l]+operAnd[l];
}
result=result+target_num[l];
document.getElementById("op").value=result + '=' + eval(result) ;
return eval(result);
}
I have html which has buttons like this:
<button class="num" onclick="getval(0)">0</button>
<button class="num" onclick="getval(1)">1</button>
<button class="num" onclick="getval(2)" >2</button>
<button class="num" onclick="getval(3)" >3</button>
......................... and so on
For the basic math, this code works fine and is not a problem. However, here is my problem from where I have hard time on thinking how to implement this. Say for example, I have a following button like this.
<button class='extra' onclick="Regression()"> Find Regression </button>
Now, I will have regression function which will ask user to input the regression type (1-linear, 2-quadratic and so on...this is just an example).
function regression(){
clearval();
document.getElementById("op").value=" Enter the degree of regression:";
which is basically asking user to enter the number and click '=' to enter into the program.
Now you can see my dilemma. Anything user inputs will be firstly processed by getval() which will pass the array to another function when user clicks '=', which is not what I will want in this case. To be clear, for this kind of case which I will have many such as std. dev or some kind of functions like this, I want the keypad to behave as normal keypad and pass the value to another function without doing normal calculator stuff as it was supposed to do.
Am I thinking this straight? Any suggestions?
I think you could solve this by adding another function called passval(), which will contain much of the same logic as getval() in terms of parsing the input into a float, etc., but which doesn't ever push values onto your operand stack or call the assembler function. It simply returns the button pushed as a nice float value to the .extra function that called it.
Then, as part of the logic in your .extra functions like Regression(), you would initially swap the onclick function for all of your buttons from getval() to passval(). When the regression or other special function is complete, swap the buttons back to their default behavior.
Well, this is what I would do(if I undestood right):
Change you button layout to this:
<input type="button" class="num" value="0" /> Removing the onclick event
Always better to use input type="button" than <button>.
Create a function to bind events to the buttons:
function bindButtonEvent(func) {
var buttons; // Here some way to get the button in a collection from the DOM tree
for (var i = 0; i < buttons.length; i++) {
buttons[i].onclick = function() { func(buttons[i]); }
}
}
With this you will got a function to change the click event of all your buttons. This will make your engine more flexible.
You will have to change your getval function a little to get the value by itself:
function getval(el){
var inp = el.value;
if(inp!="=")
So on the calculator load, you set the click function:
bindButtonEvent(getval())
When you want to call a custom behaviour function, you call the binding again:
function regression() {
bindButtonEvent(function(el) {
value = el.value;
// Do things
// When done, take bindings back.
bindButtonEvent(getval());
});
clearval();
document.getElementById("op").value=" Enter the degree of regression:";
}
NOTE: That is an ideia. I didn't tested the code. If you're interested on this and have errors on implementation, let me know, and we'll going fixing them.

Categories

Resources