6

Why magento One-Page-Checkout page has the input fields with Id's that cannot be referred to any CSS attributes or by a javascript / jquery? Does this holds any security measures ? or it can be customized to CSS / Js friendly ID's ?

How can I set the inputs First-Name and Last-Name capitalized or add a blue border to these fields alone.

8

you can still reference in css or use dom selectors for elements with : in their id.

Let's say you have this html

<div id="some:id_here">Something here</div>

you can set the styles like this:

#some\:id_here {
    width:50px;
    border: 1px solid blue;
}

you can select it via prototype dom selector:

$('some\\:id_here')

or via jQuery:

jQuery('#some\\:id_here');

the idea is that : becomes \: in the css/dom selectors and \\: for jQuery.

  • I always used selectors like input[id="billing:city"], didn't know about escaping in CSS. Thanks! – Fabian Schmengler Sep 9 '15 at 14:21
  • @Marius ... to escape meta-characters in prototype and jquery it should be two backslashes: `\\`. See api.jquery.com/category/selectors and stackoverflow.com/questions/5552462/… – Renon Stewart Sep 9 '15 at 15:00
  • @R.S. For Jquery you are right. Thanks for that. For prototype and css it works with a single backslash. Just jsFiddled it. – Marius Sep 9 '15 at 15:13
  • @Marius ... I had this same issue 2 weeks ago. In prototype this will work $('billing:street1'); without any slash beause you are using a ID selector. But this $$('#billing:city') will not. you need to add the slash because the colon (:) is been interpret as a selector (eg $$('#billing:empty') – Renon Stewart Sep 9 '15 at 15:21
3

I suppose this is because many of these elements contain addresses and they need to be differentiated between billing and shipping-related fields.

As much as it can be inconvenient, I advise against changing them because a lot of logic is bound to it and you'd end up fixing a lot more things upstream.

jQuery does support elements with a colon on the ID, you simply need to add a double backslash before the colon in the selector:

Change the border to blue

$('#billing\\:firstname').css('border-color', 'blue');
$('#billing\\:lastname').css('border-color', 'blue');

Capitalise

$('#billing\\:firstname').val($(this).val().toUpperCase());
$('#billing\\:lastname').val($(this).val().toUpperCase());
2

Magento is 2008 vintage as far as the checkout goes so you might as well stick to 2008 vintage prototype.

Like many others I too have often wanted to set names in forms to be Proper Case but implementation can be tricky. Personally I prefer backend name tidying, this is because the Google-able code to fix names (e.g. MacDonald) is better in PHP land to JS.

Here is an example of how to get things working if you do want to go full frontend. In this example just the name widget box is fixed (addresses can be just block capitalised in some use cases).

If you copy the name widget template over to your theme, e.g. to:

frontend/package/theme/template/customer/widget/name.phtml

Now add a simple script to the end:

<script>
function toTitleCase(string)
{
  return string.toLowerCase().replace(/_/g, ' ').replace(/\b([a-z\u00C0-\u00ff])/g, function (_, initial) {
    return initial.toUpperCase();
}).replace(/(\s(?:de|a|o|e|da|do|em|ou|[\u00C0-\u00ff]))\b/ig, function (_, match) {
    return match.toLowerCase();
});

} $('getFieldId('firstname')?>').observe('blur', function(e) { (this).setValue(toTitleCase((this).getValue())); }); $('getFieldId('lastname')?>').observe('blur', function(e) { (this).setValue(toTitleCase((this).getValue())); });

I don't think it is necessary to do this on the front end, in the back end you can have a helper function to make a name title case using a better algorithm, here is an example:

public function titleCase($string)
{
    $word_splitters = array(' ', '-', "O'", "L'", "D'", 'St.', 'Mc');
    $lowercase_exceptions = array('the', 'van', 'den', 'von', 'und', 'der', 'de', 'da', 'of', 'and', "l'", "d'");
    $uppercase_exceptions = array('III', 'IV', 'VI', 'VII', 'VIII', 'IX');

    $string = strtolower($string);
    foreach ($word_splitters as $delimiter) {
        $words = explode($delimiter, $string);
        $newwords = array();
        foreach ($words as $word) {
            if (in_array(strtoupper($word), $uppercase_exceptions)) {
                $word = strtoupper($word);
            } elseif (!in_array($word, $lowercase_exceptions)) {
                $word = ucfirst($word);
            }

            $newwords[] = $word;
        }

        if (in_array(strtolower($delimiter), $lowercase_exceptions)) {
            $delimiter = strtolower($delimiter);
        }

        $string = implode($delimiter, $newwords);
    }

    return $string;
}

Then, in your form controllers you can then parse the post data, e.g.:

$lastname = Mage::helper('whatever')->titleCase($post['lastname']);

I would advise against the jQuery way, the Prototype way achieves what you need to do.

  • I have used Observer to do that ' customer_save_before customer_address_save_before sales_quote_address_save_before' – Dev Sep 10 '15 at 11:38
1

To expand on @Marius answer.

To use any of the meta-characters ( such as !"#$%&'()*+,./:;<=>?@[]^`{|}~ ) as a literal part of a name, it must be escaped with with two backslashes: \. For example, an element with id="foo.bar", can use the selector $("#foo\.bar"). The W3C CSS specification contains the complete set of rules regarding valid CSS selectors. See https://api.jquery.com/category/selectors/

In jQuery, $('billing:street1') will not work because the colon (:) is been interpret as a selector (eg $('billing:eq(1)')) therefore you need to escape it using backslashes: \\.

In prototype, $('billing:street1') will work WITHOUT escaping it because you are using a ID selector.

However this will NOT work $$('#billing:street1') because you are using a css selector therefore the colon is been interpret as a selector.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.