Question

I'm facing a strange thing here. I'm working on an OpenCart, register form (index.php?route=checkout/register).
I have the form and 2 fields like this:

<span class="required">*</span> <?php echo $entry_email; ?><br />
<input type="text" name="email" value="" class="large-field" /><br />
<br />
<span class="required">*</span> <?php echo $entry_telephone; ?><br />
<input type="text" name="telephone" value="" class="large-field" />

Now: The browser interprets these 2 fields as:

<input type="email" name="email" value="" class="large-field">

and

<input type="tel" name="telephone" value="" class="large-field">

BUT if I change the email field attribute-order like so:

<input type="text" value="" class="large-field" name="email" />

then the fields are truly text types, they don't get transformed.
Attention: I only modify for the first one (email) and after that the email and the telephone are parsed correctly.

I am seeing this unexpected behavior on Firefox, Chrome and Opera,
however, if I copy the inputs in a plain html and view it, they are ok..

Any idea on what is happening, and of course why?

EDIT:
The full HTML that is sent to the browser (retrieved with web-sniffer.net) is in this pastebin: http://pastebin.com/bCXab6Kb

That means that the <input type="text" fields are already changed when php sends the HTML to the browser.
So, what (why/how) converts the <input type="text"> to type email/tel (seemingly based on name attribute) and why does this fail when the input-field's attribute order is changed?

Was it helpful?

Solution

OpenCart up to current stable version 1.5.6 (and version 1.5.6.1 as it currently is,) does not use any HTML5 (input fields etc) by default (or in it's default theme).
This is in-line with: When will opencart start to use html5? (apr. '12): "People are still complaining about IE6 support. When people stop whining about that, then we can start focusing on HTML5 transitioning".

For example, the file checkout/register.tpl (from v 1.5.6) (that you modified) contains by default:

<span class="required">*</span> <?php echo $entry_email; ?><br />
<input type="text" name="email" value="" class="large-field" />
<br />
<br />
<span class="required">*</span> <?php echo $entry_telephone; ?><br />
<input type="text" name="telephone" value="" class="large-field" />

However, in the current master-branch (dec. '13) I am seeing some inconsistent use of HTML5 input-fields in some pages (like: account/register.tpl and account/edit.tpl):

<div class="form-group required">
  <label class="col-sm-2 control-label" for="input-email"><?php echo $entry_email; ?></label>
  <div class="col-sm-10">
    <input type="email" name="email" value="<?php echo $email; ?>" placeholder="<?php echo $entry_email; ?>" id="input-email" class="form-control" />
    <?php if ($error_email) { ?>
    <div class="text-danger"><?php echo $error_email; ?></div>
    <?php } ?>
  </div>
</div>
<div class="form-group required">
  <label class="col-sm-2 control-label" for="input-telephone"><?php echo $entry_telephone; ?></label>
  <div class="col-sm-10">
    <input type="tel" name="telephone" value="<?php echo $telephone; ?>" placeholder="<?php echo $entry_telephone; ?>" id="input-telephone" class="form-control" />
    <?php if ($error_telephone) { ?>
    <div class="text-danger"><?php echo $error_telephone; ?></div>
    <?php } ?>
  </div>
</div>
<div class="form-group">
  <label class="col-sm-2 control-label" for="input-fax"><?php echo $entry_fax; ?></label>
  <div class="col-sm-10">
    <input type="text" name="fax" value="<?php echo $fax; ?>" placeholder="<?php echo $entry_fax; ?>" id="input-fax" class="form-control" />
  </div>
</div>

Note how the fax field has type="text" and the absence of tables (in favor of divs) and finally the different classnames.


That brings us to the most interesting part of your question: what (why/how) converts the <input type="text" to type email/tel (seemingly based on name attribute) and why does this fail when the input-field's attribute order is changed?.

As we can see in the HTML code sent by PHP to the browser (http://pastebin.com/bCXab6Kb), the input-field's type attributes are already changed. Thus it is not the browser or a piece of javascript that changes this.
So, assuming PHP doesn't change the code by itself, there must be something in the script(s) that PHP runs to change the code as stored in files on the harddisk before sending it to the browser: OpenCart and/or (one of) it's 'themes', 'modules', 'extensions' etc.
And since some kind of html-parser probably wouldn't mess up such a simple task, the most likely candidate is some kind of script that does a basic search and replace.

There happen to be 2 (highly related) scripts, common to OpenCart, that exactly fit this bill..

  1. OpenCart's 'modification system'
    Should you have accidentally downloaded/installed the 'latest' (development) master-branch (or are a contributer), then you'll find some files like system/engine/modification.php (and some related files and database-table) that can search for and prepend/append/replace lines of code in php/tpl files (hard-coded limitation) according to rules specified in an xml file (system/modification.xml) before the targeted php/tpl file is parsed and without modifying the original file(s).
    This rather self-explanatory xml-file basically contains 'operations' per file to modify on the fly, for example:

    <file name="system/engine/front.php">
      <operation>
        <search>
          <![CDATA[$action->getFile()]]>
        </search>
        <add position="replace">
          <![CDATA[$this->registry->get('modification')->getFile($action->getFile())]]>
        </add>
      </operation>
    </file>         
    

    where $action->getFile() is replaced with $this->registry->get('modification')->getFile($action->getFile()) before file system/engine/front.php is parsed!

  2. "vQmod™" (aka Virtual Quick Mod)
    vQmod is a separately developed package and is basically a polished version of OpenCart's modification system (above), from which it originated. It is commonly used by 'add-ons' to modify production-releases of OpenCart and installed (as it is not included in OpenCart by default) in folder vqmod (located in the root of OpenCart). Inside this folder you'll find a folder vqcache that holds the cached modified files and a folder xml that holds the xml search/replace files.
    These xml files have a slightly different syntax (most notably the position attribute) compared to OpenCart's modification system (above):

    <file name="catalog/view/theme/default/template/checkout/register.tpl">
      <operation>
        <search position="replace">
          <![CDATA[<input type="text" name="email" value="" class="large-field" />]]>
        </search>
        <add>
          <![CDATA[<input type="email" name="email" value="" class="large-field" />]]>
        </add>
      </operation>
      <operation>
        <search position="replace">
          <![CDATA[<input type="text" name="telephone" value="" class="large-field" />]]>
        </search>
        <add>
          <![CDATA[<input type="tel" name="telephone" value="" class="large-field" />]]>
        </add>
      </operation>
      <operation>
        <search position="replace">
          <![CDATA[<input type="text" name="fax" value="" class="large-field" />]]>
        </search>
        <add>
          <![CDATA[<input type="tel" name="fax" value="" class="large-field" />]]>
        </add>
      </operation>
    </file>
    

    Note: above example is from the 'embermonkey responsive theme' and is an excellent example of the behavior of what you are experiencing: it replaces the input attributes.

The purpose of these modification-scripts is to:

avoid having to change core files. The concept is quite simple... Instead of making changes to the core files directly, the changes are created as xml search/replace script files. These script files are parsed during page load as each "source" core file is loaded with the "include" or "require" php functions. The source is then patched with the script file changes, and saved to a temp file. That temp file is then substituted for the original during execution. The original source file is never altered. This results in a "virtual" change to the core during execution without any actual modification to the core files.

This makes it possible to "virtually alter any php or tpl file in OpenCart (except the main index.php)" so that it will become easier and more reliable to update OpenCart's core files and add/remove templates etc.


Finally, the valid email address (letters@gmail.com) that fails to validate when the input's type is set to email instead of text...
This is a rather common problem with (broken/outdated/partially-installed) 'responsive'/'mobile' themes etc. (that usually also affects telephone fields) 1, 2.
The problem is not that the browser rejects the valid email-addres (when the input field's type is set to email instead of text); instead, it's OpenCart's JSON validator that doesn't get input types email (and tel, etc) by default (when you or the theme left this unpatched):

$('#button-guest').live('click', function() {
   $.ajax({
      url: 'index.php?route=checkout/guest/validate',
      type: 'post',
      data: $('#payment-address input[type=\'text\'], #payment-address input[type=\'checkbox\']:checked, #payment-address input[type=\'radio\']:checked, #payment-address input[type=\'hidden\'], #payment-address select'),
      dataType: 'json',

Thus, obviously, the solution is to add these input-types to the AJAX-call:

$('#button-guest').live('click', function() {
   $.ajax({
      url: 'index.php?route=checkout/guest/validate',
      type: 'post',
      data: $('#payment-address input[type=\'text\']
             , #payment-address input[type=\'email\']   // added
         //  , #payment-address input[type=\'tel\']     // added
             , #payment-address input[type=\'checkbox\']:checked
             , #payment-address input[type=\'radio\']:checked
             , #payment-address input[type=\'hidden\']
             , #payment-address select'
             ),
      dataType: 'json',

In conclusion, using what is explained above:

  • Most probably you either installed some kind of 'Complete'/'Popular' re-distribution of OpenCart that included vQmod or you upgraded an existing OpenCart installation that included vQmod or you installed some kind of add-on that depends on vQmod and installed that by itself.
  • To find and disable this mod you'd first search your OpenCart directory for a folder called 'vQmod'. If you can not find it, you do a text-search (starting in your OpenCart directory and including subdirectories) for strings containing <input type="email" (for example) and investigate results with file-type xml first.
  • To use the mod without having validation (of email, telephone, fax, etc) fail, fix the JSON call (you could use vQmod should it be already installed and just add this as an operation for the affected files).
  • Alternatively (as you have already noticed), have the mod crash by changing the attribute order (at the price of other mods for this page also failing as you noticed).
  • If none of the above works in your case, I'd highly recommend to re-install a clean version of OpenCart!

PS: now you know of vQmod, you'd better use it (instead of modifying core-files) since "performance suprisingly does not appear to be a factor at all", giving you the benefit of a more reliable upgrade-path in the future!

OTHER TIPS

Actually the behaviour You are describing is not coming from OpenCart at all - at least not from the default installation with the default theme.

You can turn off the JS and access this page directly: http://your.ocinstall.com/index.php?route=account/register - it will open the registration page.

Anyway, in default installation (and default theme) there is this HTML:

    <tr>
      <td><span class="required">*</span> <?php echo $entry_email; ?></td>
      <td><input type="text" name="email" value="<?php echo $email; ?>" />
        <?php if ($error_email) { ?>
        <span class="error"><?php echo $error_email; ?></span>
        <?php } ?></td>
    </tr>
    <tr>
      <td><span class="required">*</span> <?php echo $entry_telephone; ?></td>
      <td><input type="text" name="telephone" value="<?php echo $telephone; ?>" />
        <?php if ($error_telephone) { ?>
        <span class="error"><?php echo $error_telephone; ?></span>
        <?php } ?></td>
    </tr>

but in Firefox still the order of attributes is changed (but not the attribute values!):

<input type="text" value="" name="email" />

Same in Chrome - no attribute values are changed. The only reason may be the JavaScript library and/or another theme being used.

Though the doctype of HTML of OpenCart's default theme is defined as HTML5, OpenCart actually does not use any HTML5 feature.

Anyway, if there is something making the real use of HTML5 in Your template then do not be afraid and enjoy these features. For example in the very example from Your question, if the input has type email or tel, then user cannot submit the form until the email field contains semantically correct email address and he is even not able to fill in any literal (non-numeric) characters into the tel field... (Yep, until the user modifies the HTML via developer tools...)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top