Implementing money.js on multiple fields on same page - php

I'm struggling with conceptually how to implement this (what events to bind to etc).
I'm using CakePHP and have a view with the following:
An array of products to display and an associated price ($products['Product']['price'])
Each product has a base currency set ($product['Currency]['currency'])
I have money.js, accounting.js and another JS that sets JSON data for fx.rates and fx.base
I know the currency that the user wants to see and will likely differ from the product base currency (SessionComponent::read('User.Preferences.Currency')
A div to display the currency shortname (USD) and converted value, each div with unique id
My simple test works fine - using inline-php I've put a bit of JS on the page between two script tags.
<script>
var value = accounting.unformat(<? echo $product['Product']['price'] ?>); // clean up number (eg. user input)
var target = "<? echo SessionComponent::read('User.Preference.currency'); ?>"; // or some user input
var convertedValue = fx(value).from("<? echo $product['Currency']['currency'] >").to(target);
accounting.formatMoney(convertedValue, {
symbol: target,
format: "%v %s"
}); // eg. "53,180.08 GBP"
alert(convertedValue);
</script>
Fine. Works great. But what I can't work out is how to implement this on a page with N number of products.
I'm assuming I create a JS function, something like:
fx_convert(divid, price, fromcurrency, tocurrency)
And in my Cake view, I use inline php to echo the function parameters.
What is the clean way to use jQuery for this function, and have the price 'divs' call fx_convert and update their content with the converted value?
Or is my thinking totally backwards on this? All help is greatly appreciated.

After some decent sleep, figured it out. :)
Using inline PHP, I pass the to/from currencies via the div attributes and set a uniform class name. e.g.
<div class="fx" fx-from="<?php echo $product['Currency']['currency']; ?>" fx-to="<?php echo SessionComponent::read('User.Preference.currency') ?>" fx-value="<?php echo $product['Product']['price']; ?>"></div>
And then use the following jQuery snippet to loop over all elements of class "fx" and do the required calculation (using the excellent money.js and accounting.js)
$(document).ready(function() {
$(".fx").each( function( index, element ){
var value = accounting.unformat($(this).attr("fx-value")); // clean up number (eg. user input)
var target = $(this).attr("fx-to"); // or some user input
var convertedValue = fx(value).from($(this).attr("fx-from")).to(target);
$(this).html(accounting.formatMoney(convertedValue, {
symbol: target,
format: "%v %s"
}));
});
});
Still need to refactor and tidy up, but the solution is there.

Related

jquery pull textarea values based on which checkboxes were checked

I'm working on a project that involves returning the id of the checkboxes chosen as well as the text in the corresponding textarea fields for those chosen checkboxes. The data is dynamically displayed and so far my jquery pull of both the checkboxes and textareas work:
var noteList = $("textarea[name='revokeNotes']").map(function(){
return this.value;
}).get().join();
var revokeList = $("input[name='revoke']:checked").map(function(){
return this.id;
}).get().join();
but I'm getting back all of the notes fields and I'm uncertain how to best iterate through them to find the proper notes as their ids aren't sequential but rather based on their id in the table they are being pulled from. The last version of the display code is below:
<td><textarea name=\"revokeNotes\" id=\"".$v["id"]."\" cols=\"30\"rows=\"3\">".$v["notes"]."</textarea></td>
<td><input type=\"checkbox\" id=\"".$v["id"]."\" name=\"revoke\" value=\"".$v["id"]."\" /></td>
Is there a way to reach my goal from this state or should I be using another jquery function, similar to .map()? I thought about using the id field from the checkboxes to iterate through the selected notes and pushing them into an array but I'm not sure 1) if that will work and 2) how to do that.
I need the data back in some form either an array or something I can explode on in php to create an array as I'm passing one value in ajax as there is no set maximum or minimum number of rows that will be displayed per user. Map was working until I threw some commas at it. Extra points for that.
var noteList = $.map(
$("textarea[name='revokeNotes']").filter(function() {
return $(this).closest('td')
.next('td')
.find('input[type="checkbox"]')
.is(':checked');
}), function(el) {
return el.value;
}).join();
adeneo's answer is great, I'd just propose the following improvements:
If possible use class selectors (like '.revoke-notes-area') since those are faster than DOM + attr selectors
Assuming this is a table and there is one textarea checkbox combo per row, you can traverse the tree to the closest <tr> a decouple the JS from depending that the checkbox comes after the text area in the DOM.
var filterMethod = function() {
$(this).closest('tr').find('.revoke-checkbox').is(':checked');
};
var mapMethod = function(el) {
return el.value;
};
var nodeList = $.map($('.revoke-notes-area').filter(filterMethod), mapMethod);
There's no reason you cannot or should not put the filter and map methods inline, I just split them out into variables so it's easier to read here.
You can check out my codepen here: http://codepen.io/aaron/pen/eIpby.

Dynamically changing photo with dropdown

I am new to PHP and am trying to figure out how to code some specific functionality. I have a product page that shows a photo and has two dropdown menus, one for size and one for color. What I would like to do is when the page first loads I set a variable that has the default product SKU. When the menus change I want to change the variable to the combined values of the two menu items selected. As the variable changes I want to reflect this in the photo and in a hidden form value (for eventual submission to a cart).
So when the page loads it shows picture A with the associated values in the size and color dropdowns. Then when either of the dropdowns change the photo dynamically changes to reflect it (while also updating the hidden form value).
Any suggestions would be much appreciated.
JavaScript, or a JS library like jQuery, is what you need here.
For jQuery (preferred, way easier):
var $select = $('#Dropdown'),
$img = $('#Picture');
$select.on('change',function(){
$img.attr('src',$(this).val());
});
For JavaScript:
var dropdown = document.getElementById('Dropdown'),
img = document.getElementById('Picture');
dropdown.addEventListenter('change',function(){
img.src = this.value;
});
Not tested, but should work.
Edit: when using the JavaScript solution, make sure the window is loaded first (it won't work if the elements dont exist yet).
window.onload = function(){
// do your magic here
}
Firstly, PHP is a server side language which effectively means, anything that it generates must be processed by the server and then sent back to the browser. Therefore in this particular case, you need to use a client side language such as Javascript, or to make the code easier, a library such as jQuery.
To learn more about jQuery, see here:
http://jquery.com/
In very generalised terms (as you have not posted any code), here is an example of changing
an image using jQuery:
// Select the dropdown from the DOM
var dropdown = $('#dropdown_id');
// Select the image from the DOM
var image = $('#image');
// Set the onchange event
// This will be fired when the select value is changed
dropdown.on('change',function(){
// Get the value of the selected option
var value = $(this).val();
// Change the source of the image
image.attr('src',value);
});

Removing IDs from HTML elements before saving them to database

I am working on a application which can save user-created HTML templates. Here, the user will have some HTML components at his disposal and would be able to create static HTML pages using those components.
I am auto saving the content of the page using a javascript function.
function saveContent(){
//var getContent=$('#mainWrap').children().removeAttr('id');
var $getContent=$('#mainWrap');
var $finalContent=$getContent.children().removeAttr('id');
var auto="auto";
var pageId = <?php echo $pageId;?>;
var webId = <?php echo $webId;?>;
var userId = <?php echo $userId;?>;
$.ajax({
url:"auto_save.php",
type:"POST",
dataType:"text",
data:"txtComp="+$('#mainWrap').html()+"&auto="+auto+"&pageId="+pageId+"&webId="+webId+"&userId="+userId
});
}
var interval = 1000 * 60 * 0.30; // where X is your every X minutes
setInterval(saveContent,interval);
Issue: I want to to remove the IDs from the HTML components that the user saves, because the IDs are auto generated and not needed when the user publishes the template (on his domain after creation). I have a main wrapper that wraps the entire page called id=mainWrap. If I try to remove the IDs like this $('#mainWrap').children().removeAttr('id'); they are also removed from the current context of the DOM, i.e they are removed from the page where the user is editing his template.
Question: How can I remove the IDs from the HTML elements without affecting the current context of the mainWrap object?
I tried assigning it to another object like this
var $getContent=$('#mainWrap');
var $finalContent=$getContent.children().removeAttr('id');
but still it failed.
Any comments or corrections on whether this is possible? Or am I going about this the wrong way?
Update : The issue is solved to some extent.
Next I want to add the id's back when the user comes back to the edit page.
I get the above saved content using this code
<?php
$sqlEdit = "select revisionContent from tbl_revision where revisionId='".$_SESSION['contentId']."'"; //The query to get the record
$rsEdit = $dbObj->tep_db_query($sqlEdit);//The database object to execute the query
$resEdit = $dbObj->getRecord($rsEdit);
$IdLessContent = $resEdit['revisionContent'];//Variable with the record
?>
Now,I want to use this PHP variable in javascript,so I did this.
<script language="javascript">
var getSavedContent = '<?php echo json_encode($IdLessContent); ?>';
var trimmedCont=($.trim(getSavedContent).slice(1));
//console.log(trimmedCont);
var lengthCont= trimmedCont.length;
var trimmedCont=$.trim(trimmedCont.slice(0,lengthCont-1));
var pageContent=$('<div class="addId">').append(trimmedCont); //Here I tried creating a div dynamically and appending the content to the div.But now I am not able to manipulate or work on this dyamic div and get NULL when I alert saying $('.addId').html();
$('.addId').children().attr('id', 'test'); //I tried doing this but does not work
This is not working.Can you throw some light on it
You can just cycle through the elements in your #mainWrap and remove the id like:
var getContent = $('#mainWrap');
var finalContent = getContent.parent().clone().find('*').removeAttr('id');
Example: http://jsfiddle.net/7m8g4/6/
Security wise you should realize this is a client-side script that is removing the id attributes from the html. There are ways though to manipulate the JavaScript or to bypass it by (for instance) calling the URL in your Ajax request directly with false data.
So you should never rely on your JavaScript only. Make sure your code will not cause problems if for any reason the JavaScript doesn't act as expected. You can do this for instance by searching for id attributes (use a regex) and generate an error message in case there are still some id attributes found. Another way would be to remove them server-side (in PHP) as well if any are found. To achieve this you could do a regex search and replace the matches with empty strings or by making use of substrings. Up to you!
Hope it all makes sense!
EDIT
If you want to add new id attributes back later on you can do something like:
var newContent = $(finalContent).first().wrap('<div class="addId" />');
newContent = $(newContent).parent().find('*').each(function(index, value) {
$(this).attr('id', index);
});
See that in work here.

Unable to get attr of looped out PHP variable with Jquery $().attr

Hi all got a small problem accessing a looped php variable. My script loops through and uses x and y from a mysql database. It also loops the id out which I cannot get access to, it comes up as undefined. I am using a mouse out function to detect each separate div that has been looped and get specific id.
Help very much appreciated!
Javascript to get attributes ready for database manipulation:
$(this).mouseout(function() {
var stickytext_id = $(this).attr('textstickyid');//alerted out returns undefined.
});
Looped PHP to get attr form:
$get_textsticky_result=mysql_query($get_textsticky_query);
while($row=mysql_fetch_assoc($get_textsticky_result)){
$x = $row['textsticky_x'];
$y = $row['textsticky_y'];
echo '<div class="textsticky" style="position: absolute; left:'.$x.'px; top:'.$y.'px;" textstickyid="'.$row['textsticky_id'].'">
<div class="textstickyvalueholder"contentEditable="true">'. $row['textsticky_text'] .'
</div><button>Like</button></div>';
}
?>
Can get other looped vars e.g. $row['textsticky_text']; and x and y for position without issue, Is there a better way to do this? I have a feeling the inline style is affecting it but not sure....
Okay, I am just going to go out on a limb here and assume your initial selector is incorrect. $(this) is the window in typical code flow.
$(this).mouseout(function() {
var stickytext_id = $(this).attr('textstickyid');//alerted out returns undefined.
});
Should be:
$('div.textsticky').mouseout(function() {
var stickytext_id = $(this).attr('textstickyid');//alerted out returns undefined.
});
Also, as Kris mentioned in comments, instead of inventing tags use the data attribute which is a part of html5.
<div class="textsticky" data-textstickyid="blah" />
It can then be accessed via jQuery's data method.
http://jsfiddle.net/kQeaf/
And as long as we are offering advice, if you are in jQuery 1.7+ you should be using prop instead of attr for accessing properties (unless of course you decide to use the data method) just recommended.
Your selector on the mouseout event may be wrong: (depending on the context)
$(".textsticky").mouseout(function() {
var stickytext_id = $(this).attr('textstickyid');
});

jQuery: Using autocomplete to add values to two fields instead of one

I want to use the autocomplete plugin for jQuery to populate not one, but two fields when selecting one of the autocomplete values - the name of a band is entered in the #band input field, but the band url (if exists) should also automatically be added to the #url input field when selecting the band name.
Right now I simply have an un-pretty list in an external php file from which the autocompleter takes it's values:
$bands_sql = "SELECT bands.name, bands.url
FROM bands
ORDER BY name";
$bands_result = mysql_query($bands_sql) or print (mysql_error());
while ($bands_row = mysql_fetch_array($bands_result)) {
$band_name = $bands_row['name'];
$band_url = $bands_row['url'];
echo $band_name."\n"; #needs to be replaced with an array that holds name and url
}
My autocomplete function looks very basic atm, but as I'm an absolute beginner when it comes to jQuery (and also clueless when it comes to PHP arrays), I have no idea how to tell it to populate two fields and not one.
$(document).ready(function() {
$("#band").autocomplete('/autocomplete-bands.php');
});
Is that even possible?!
sure check use result hadler so you can then do what you want once a choice has been made
I don't know about the particular plug-in you are using, but I would use the autocomplete widget for jQuery UI instead of a third party plug-in.
Here is an example of what you are looking for:
$("#band").autocomplete('/autocomplete-bands.php').result(function(event, data, formatted) {
if (data)
$('#url').(data['url']);
else {
// no data returned from autocomplete URL
}
});
I don't know much about php, but whatever the format of your data that is returned should be put where the data['url'] is currently in order to populate the #url input.

Categories