Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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());

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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top