I have to many custom options on product page.
I would like to fill out the empty space on the left with a static block that appear only if more there is more than 4 custum options in product view.
http://goo.gl/Y7JMQf
Step1: Display the static block content using
<div class="css_class_of_container" id="ID_OF_THE_STATIC_BLOCK_CONTAINER">
<?php
echo Mage::getModel('cms/block')
->load('STATIC_BLOCK_IDENTIFIER')
->toHtml();
?>
</div>
Step2: Add css to hide the static block container by default using
.css_class_of_container { display: none;}
Step3. Use javascript to show and hide the static block based on the number of custom options available.
in app/design/package/theme/catalog/product/view/options.phtml
<?php if (count($_options)):?>
<script type="text/javascript">
<?php if(count($_options) > 4):?>
//if you are using jquery
jQuery(document).ready(function(){
jQuery("#ID_OF_THE_STATIC_BLOCK_CONTAINER").show();
});
//if using native javascript
setTimeout('showhiddenStaticBlock()', 500);
function showHiddenStaticBlock() {
document.getElementById("ID_OF_THE_STATIC_BLOCK_CONTAINER").style.display = 'block';
}
<?php endif;?>
</script>
<?php endif;?>
Related
This seems to be the easiest thing to do, but it's just not working. In a normal browser the .html and .js files works perfectly, but in the Chrome/Firefox extension the onClick function is not performing what it's supposed to do.
.js file:
function hellYeah(text) {
document.getElementById("text-holder").innerHTML = text;
}
.html file:
<!doctype html>
<html>
<head>
<title>
Getting Started Extension's Popup
</title>
<script src="popup.js"></script>
</head>
<body>
<div id="text-holder">
ha
</div>
<br />
<a onClick=hellYeah("xxx")>
hyhy
</a>
</body>
</html>
So basically once the user clicks "hyhy", "ha" should change into "xxx". And again - it works perfectly in the browser but does not work in the extension. Do you know why? Just in case I'm attaching the manifest.json below as well.
manifest.json:
{
"name": "My First Extension",
"version": "1.0",
"manifest_version": 2,
"description": "The first extension that I made.",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"http://api.flickr.com/"
]
}
Chrome Extensions don't allow you to have inline JavaScript (documentation).
The same goes for Firefox WebExtensions (documentation).
You are going to have to do something similar to this:
Assign an ID to the link (<a onClick=hellYeah("xxx")> becomes <a id="link">), and use addEventListener to bind the event. Put the following in your popup.js file:
document.addEventListener('DOMContentLoaded', function() {
var link = document.getElementById('link');
// onClick's logic below:
link.addEventListener('click', function() {
hellYeah('xxx');
});
});
popup.js should be loaded as a separate script file:
<script src="popup.js"></script>
Reason
This does not work, because Chrome forbids any kind of inline code in extensions via Content Security Policy.
Inline JavaScript will not be executed. This restriction bans both inline <script> blocks and inline event handlers (e.g. <button onclick="...">).
How to detect
If this is indeed the problem, Chrome would produce the following error in the console:
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' chrome-extension-resource:". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution.
To access a popup's JavaScript console (which is useful for debug in general), right-click your extension's button and select "Inspect popup" from the context menu.
More information on debugging a popup is available here.
How to fix
One needs to remove all inline JavaScript. There is a guide in Chrome documentation.
Suppose the original looks like:
<a onclick="handler()">Click this</a> <!-- Bad -->
One needs to remove the onclick attribute and give the element a unique id:
<a id="click-this">Click this</a> <!-- Fixed -->
And then attach the listener from a script (which must be in a .js file, suppose popup.js):
// Pure JS:
document.addEventListener('DOMContentLoaded', function() {
document.getElementById("click-this").addEventListener("click", handler);
});
// The handler also must go in a .js file
function handler() {
/* ... */
}
Note the wrapping in a DOMContentLoaded event. This ensures that the element exists at the time of execution. Now add the script tag, for instance in the <head> of the document:
<script src="popup.js"></script>
Alternative if you're using jQuery:
// jQuery
$(document).ready(function() {
$("#click-this").click(handler);
});
Relaxing the policy
Q: The error mentions ways to allow inline code. I don't want to / can't change my code, how do I enable inline scripts?
A: Despite what the error says, you cannot enable inline script:
There is no mechanism for relaxing the restriction against executing inline JavaScript. In particular, setting a script policy that includes 'unsafe-inline' will have no effect.
Update: Since Chrome 46, it's possible to whitelist specific inline code blocks:
As of Chrome 46, inline scripts can be whitelisted by specifying the base64-encoded hash of the source code in the policy. This hash must be prefixed by the used hash algorithm (sha256, sha384 or sha512). See Hash usage for <script> elements for an example.
However, I do not readily see a reason to use this, and it will not enable inline attributes like onclick="code".
I had the same problem, and didnĀ“t want to rewrite the code, so I wrote a function to modify the code and create the inline declarated events:
function compile(qSel){
var matches = [];
var match = null;
var c = 0;
var html = $(qSel).html();
var pattern = /(<(.*?)on([a-zA-Z]+)\s*=\s*('|")(.*)('|")(.*?))(>)/mg;
while (match = pattern.exec(html)) {
var arr = [];
for (i in match) {
if (!isNaN(i)) {
arr.push(match[i]);
}
}
matches.push(arr);
}
var items_with_events = [];
var compiledHtml = html;
for ( var i in matches ){
var item_with_event = {
custom_id : "my_app_identifier_"+i,
code : matches[i][5],
on : matches[i][3],
};
items_with_events.push(item_with_event);
compiledHtml = compiledHtml.replace(/(<(.*?)on([a-zA-Z]+)\s*=\s*('|")(.*)('|")(.*?))(>)/m, "<$2 custom_id='"+item_with_event.custom_id+"' $7 $8");
}
$(qSel).html(compiledHtml);
for ( var i in items_with_events ){
$("[custom_id='"+items_with_events[i].custom_id+"']").bind(items_with_events[i].on, function(){
eval(items_with_events[i].code);
});
}
}
$(document).ready(function(){
compile('#content');
})
This should remove all inline events from the selected node, and recreate them with jquery instead.
I decide to publish my example that I used in my case. I tried to replace content in div using a script. My problem was that Chrome did not recognized / did not run that script.
In more detail What I wanted to do: To click on a link, and that link to "read" an external html file, that it will be loaded in a div section.
I found out that by placing the script before the DIV with ID that
was called, the script did not work.
If the script was in another DIV, also it does not work
The script must be coded using document.addEventListener('DOMContentLoaded', function() as it was told
<body>
<a id=id_page href ="#loving" onclick="load_services()"> loving </a>
<script>
// This script MUST BE under the "ID" that is calling
// Do not transfer it to a differ DIV than the caller "ID"
document.getElementById("id_page").addEventListener("click", function(){
document.getElementById("mainbody").innerHTML = '<object data="Services.html" class="loving_css_edit"; ></object>'; });
</script>
</body>
<div id="mainbody" class="main_body">
"here is loaded the external html file when the loving link will
be clicked. "
</div>
As already mentioned, Chrome Extensions don't allow to have inline JavaScript due to security reasons so you can try this workaround as well.
HTML file
<!doctype html>
<html>
<head>
<title>
Getting Started Extension's Popup
</title>
<script src="popup.js"></script>
</head>
<body>
<div id="text-holder">ha</div><br />
<a class="clickableBtn">
hyhy
</a>
</body>
</html>
<!doctype html>
popup.js
window.onclick = function(event) {
var target = event.target ;
if(target.matches('.clickableBtn')) {
var clickedEle = document.activeElement.id ;
var ele = document.getElementById(clickedEle);
alert(ele.text);
}
}
Or if you are having a Jquery file included then
window.onclick = function(event) {
var target = event.target ;
if(target.matches('.clickableBtn')) {
alert($(target).text());
}
}
I can add a script to a page via the dashboard (by editing the page Content Item as html). The script is added to the page and evaluated, but too early - none of scripts are loaded yet (for example, jQuery).
I don't want to add the script to Layout, as it makes no sense to add this script for all pages.
Is there any way to add a script to a single page's content via the dashboard, so that it can be evaluated properly?
Or should I create a separate module that contains a special content part (to include proper scripts for the view/shape) and add that part to a custom ContentType (that also contains BodyPart and others such as Page Content Items)?
Or should I separate the whole content in such a way that interactive parts are widgets and should not be edited in Page Content Item?
Can you use the Script.Foot() extension method ?
#using(Script.Foot()) {
...
}
Using jQuery from Orchard module page
You can add the script file to the top of the html content like below:
<p>
<script type="text/javascript" src="/*path of the file*/">// <![CDATA[
// ]]></script>
</p>
Steps to add: Dashboard->Content->open the particular page->Html source editor->In the top add the above script with your script file path.
I suggest adding a part for your script, something like:
public class CustomScriptPart : ContentPart<CustomScriptPartRecord>
{
public bool AtFoot
{
get { return Record.AtFoot; }
set { Record.AtFoot = value; }
}
public string Script
{
get { return Record.Script; }
set { Record.Script = value; }
}
}
Views/Parts/CustomScript.cshtml
#if(Model.AtFoot) {
using(Script.Foot()) {
<script type="text/javascript">
#Model.Script
</script>
}
} else {
<script type="text/javascript">
#Model.Script
</script>
}
But probably something similar is already done, by Vandelay Industries for example.
How do I create a component (like a footer section) and include it on a page?
I read stuff like markup inheritance, but that doesnt sound right (how would you re-use a footer section component in different pages when it can only inherit from a single page).
This is my 2nd day of using Wicket and wicket-library.com has some great examples, but at the moment it seems to be down when you try to view the source.
Thank you.
Create a basepage with header, footer, menu etc. Then extend you pages from that page. Use it like this:
public class BasePage extends WebPage {
public BasePage() {
add(new HeaderPanel("header"),
new FooterPanel("footer"),
new MenuPanel ("menu" ));
}
}
With this html:
<html xmlns:wicket>
<body>
<div wicket:id="header">
<div wicket:id="menu">
<wicket:child></wicket:child>
<div wicket:id="footer">
</body>
</html>
You would need to create a HeaderPanel, FooterPanel and MenuPanel.
Your child page example:
public class MyPage extends BasePage { ...}
Which has this html:
<html xmlns:wicket>
<body>
<wicket:extend>
</wicket:extend>
</body>
</html>
You can also create a no-menu basepage etc. The components and html you add to your child page will be placed between the tags of the basepage.
How to disable particular layout(example:menus.phtml) for particular pages in controller in ZF2?? In the below example menus.phtml should be disable for specific pages. Remaining pages must contain menus.phtml like header and footer.
<div>
header.phtml
</div>
<div>
menus.phtml
</div>
<div>
<?php echo $this->content; ?>
</div>
<div>
footer.phtml
</div>
There are various aproaches to this. Also modules.zendframework has quite a few modules here that may help you out.
If you are still keen on writing that yourself you could add variables to your layout within your controllers like so:
<?php
//YourController.php
public function someAction()
{
...
$this->layout()->footer = 'default';
...
}
//layout.phtml
<?php if ($this->footer === 'default') : ?>
//show the footer
<?php endif; ?>
Doing this is pretty inefficient though. Just imagine you'd need to do this to every action in all the controllers... I sure would not like to do that.
Now zf2 has a service and event layer that could help us out quite a bit here. This is a pretty nice read and introduction to it. You'd just write a service and trigger a event on your controllers/routes/whatever. Now you would also probably like to configure what is shown and what is hidden right? Thats pretty easy, too. Just write yourself a config file and merge it with the global.config like so:
<?php
//CustomModule/module.php
public function getConfig() {
$config = array();
$configFiles = array(
include __DIR__ . '/config/module.config.php',
include __DIR__ . '/config/module.customconfig.php',
);
foreach ($configFiles as $file) {
$config = \Zend\Stdlib\ArrayUtils::merge($config, $file);
}
return $config;
}
Source: Where to put custom settings in Zend Framework 2?
First, get the controller or action name:
$controllerName =$this->params('controller');
$actionName = $this->params('action');
then in your layout/view script add a simple logic.
<?php if ($actionName != 'action that you want to disable the layout/menu'): ?>
echo $this->render('menus.phtml');
<?php endif; ?>
I'm attempting to put a bit of style on a specific set of exposed filters on a view that I have created.
The view is called user_search and so I have created views-exposed-form--user-search.tpl.php and that didn't work (all it did was remove the exposed filters but still displayed the view). views-exposed-form--user-search--page.tpl.php also got the same results.
Even if it did work, I still don't know what to put there to get the form to show up, just so that I can add styles or container divs.
print drupal_render($form); did not work.
I found a solution after a lot of digging.
First, you have to find the views-exposed-form.tpl.php file which should be located in sites/all/modules/views/theme/ folder. We're using the acquia stack so it was located in the vendor/ folder.
Copy this to themes/YOUR-THEME/ folder and rename it to views-exposed-form--your-view-name.tpl.php
If you only want to effect a specific display of your view name it to views-exposed-form--your-view-name--display.tpl.php
You can then use the existing framework to edit it as you see fit. Here's an example.
<?php
// $Id: views-exposed-form.tpl.php,v 1.4.4.1 2009/11/18 20:37:58 merlinofchaos Exp $
/**
* #file views-exposed-form.tpl.php
*
* This template handles the layout of the views exposed filter form.
*
* Variables available:
* - $widgets: An array of exposed form widgets. Each widget contains:
* - $widget->label: The visible label to print. May be optional.
* - $widget->operator: The operator for the widget. May be optional.
* - $widget->widget: The widget itself.
* - $button: The submit button for the form.
*
* #ingroup views_templates
*/
?>
<?php if (!empty($q)): ?>
<?php
// This ensures that, if clean URLs are off, the 'q' is added first so that
// it shows up first in the URL.
print $q;
?>
<?php endif; ?>
<div class="views-exposed-form">
<div class="views-exposed-widgets clear-block">
<?php foreach($widgets as $id => $widget): ?>
<div class="views-exposed-widget">
<?php if (!empty($widget->label)): ?>
<label for="<?php print $widget->id; ?>">
<?php print $widget->label; ?>
</label>
<?php endif; ?>
<?php if (!empty($widget->operator)): ?>
<div class="views-operator">
<?php print $widget->operator; ?>
</div>
<?php endif; ?>
<div class="views-widget">
<?php print $widget->widget; ?>
</div>
</div>
<?php endforeach; ?>
<div class="views-exposed-widget">
<?php print $button ?>
</div>
</div>
</div>
When in doubt about how to theme a part of a page, install the Theme Developer module. It will allow you to see what theme file or function is currently outputting a specific area of the page, as well as what files or functions can be used to override it. See the screencast for more detailed information.