Magento: How to add the widget button to the WYSIWYG Products Editor - wysiwyg

I want to allow adding the Catalog Product Link widget in the description field of a product (so I can easily link to other products in the description). I've already extended Mage_Catalog_Model_Product by creating a file like:
class mymodule_Catalog_Model_Product extends Mage_Catalog_Model_Product
{
/**
* Add getDescription function that interprets widget or static blocks
* within product descriptions
*/
public function getDescription() {
$processor = Mage::getModel('widget/template_filter');
$html = $processor->filter($this->getData('description'));
return $html;
}
}
Now it works fine if I type something like
{{widget type="catalog/product_widget_link" anchor_text="my text" template="catalog/product/widget/link/link_inline.phtml" id_path="product/1234"}}
into the description field -- it creates a link to the product Id 1234.
But I want to add the actual Catalog Product Link widget button in the WYSIWYG editor for editing a product. The button is already in the CMS editor, but I am missing what I need to modify in order to add this widget to the Admin interface for editing a product. Can someone help me out?

For anybody stumbling across this later on like myself, you can use the cms_wysiwyg_config_prepare event to set this to true.
E.G:
in config.xml
<events>
<cms_wysiwyg_config_prepare>
<observers>
<webtise_widgets>
<class>webtise_widgets/observer</class>
<method>cmsWysiwygConfigPrepare</method>
</webtise_widgets>
</observers>
</cms_wysiwyg_config_prepare>
</events>
In your observer
<?php class Webtise_Widgets_Model_Observer{
public function cmsWysiwygConfigPrepare(Varien_Event_Observer $observer){
$observer->getEvent()->getConfig()->setAddWidgets(true);
}
}

I was able to do this by overriding the core file
app/code/local/Mage/Adminhtml/Block/Catalog/Helper/Form/Wysiwyg/Content.php
and setting
$config['add_widgets'] = true;
Now the widget button shows up in all WYSIWIG editors in the admin interface.

Related

Example showing Multi Edit in Nattable

I have a requirement wherein on a single click in the cell, normal editing must be possible and on double clicking in the cell a dialog should open for editing the cell. The two are possible individually. I see a method "boolean supportMultiEdit(IConfigRegistry configRegistry, List configLabels)" but there is no example to show the working. Has anyone used it or can show it's configuration.
Multi edit means it is possible to edit multiple cells at once. This is of course done in an editor, as it makes no sense to perform multi edit inline. You should rather have a look at openInline(IConfigRegistry, List<String>) or even better the EditConfigAttributes#OPEN_IN_DIALOG to solve what you are looking for.
But you are actually seeking for a way to handle opening an editor differently on different UI interactions. So you need to register the corresponding UI bindings. This is already discussed in the NatTable Forum.
And the EditorExample shows quite a lot of possible configuration options available for editing. And almost every editable example shows multi editing capabilities. You simply need to select multiple cells you want to edit and then start typing or pressing F2.
The following code would do the trick with a configuration based on a label that is added in the UI binding action:
public class OpenEditorConfiguration extends AbstractRegistryConfiguration {
#Override
public void configureRegistry(IConfigRegistry configRegistry) {
configRegistry.registerConfigAttribute(
EditConfigAttributes.OPEN_IN_DIALOG,
Boolean.TRUE,
DisplayMode.EDIT,
"open_in_dialog");
}
#Override
public void configureUiBindings(UiBindingRegistry uiBindingRegistry) {
uiBindingRegistry.registerDoubleClickBinding(
new CellEditorMouseEventMatcher(GridRegion.BODY),
new IMouseAction() {
#Override
public void run(NatTable natTable, MouseEvent event) {
int columnPosition = natTable.getColumnPositionByX(event.x);
int rowPosition = natTable.getRowPositionByY(event.y);
ILayerCell cell = natTable.getCellByPosition(columnPosition, rowPosition);
cell.getConfigLabels().add("open_in_dialog");
natTable.doCommand(new EditCellCommand(
natTable,
natTable.getConfigRegistry(),
cell));
}
});
}
}

Control Wicket wizard's flow by setting setComplete(boolean)

Hey there I'm still trying to improve a customized Wicket Wizard to display the steps with following states: active, completed, pending. Therefore the information of isCompleted(); should return the right value. Refering to a previous question, isComplete(); returns true, if the wizard can go to the next step.
How can I manipulate this information to get the full advantage of my draft? E.g. in one WizardStep I have multiple input fields.
super(new ResourceModel("daten.title"), new ResourceModel("daten.summary"));
java.util.Collections.addAll(sprachen, "Deutsch","English","Français","Italiano");
add(name = new RequiredTextField<String>("name", Model.of("")));
add(vorname = new RequiredTextField<String>("vorname", Model.of("")));
add(strasse = new RequiredTextField<String>("strasse", Model.of("")));
add(ort = new RequiredTextField<String>("ort", Model.of("")));
...
I don't want the step to "be completed" until each field is filled out. To check the condition I'd have to add an AjaxListener to each component and check for it's state to setComplete(boolean);. Can I control this flow from outside the wizard form? For example with an implementation of ICondition or is there another way? Because basically I can't go to the next step, because all of my textfields are RequiredTextField and cannot be skipped.
Any suggestions are highly appreciated.
Update / Solution
Component buttonbar = getForm().get(Wizard.BUTTONS_ID);
buttonbar.setOutputMarkupId(true);
Just get(Wizard.BUTTONS_ID); won't work.
Thanks to Sven Meier for the hint!
You'll have to add an AjaxFormComponentUpdatingBehavior to all your form components.
Then override #onEvent() in your wizard:
public MyWizard(id, WizardModel model) {
super(id, model);
get(Wizard.BUTTONS_ID).setOutputMarkupId(true);
}
public void onEvent(IEvent<?> event) {
if (event.getPayload() instanceof AjaxRequestTarget) {
((AjaxRequestTarget)event.getPayload()).add(get(Wizard.BUTTONS_ID));
}
}
Let your step#isComplete() return true depending on its model values, this way the wizard buttons will always be up to date.

How to user custom Drag Appearance in smart gwt

I am trying to user Custom Drag appearance in smart gwt. how can i implement it.
Current when using DragAppearance.TRACKER its show on 10px square i want a lable with caption Drag to Lineup.
vLayout1.setDragAppearance(DragAppearance.TRACKER);
vLayout1.setCanHover(true);
vLayout1.setCursor(Cursor.HAND);
I hope, the following links will help you
https://github.com/moravianlibrary/MEditor/blob/master/editor-editation/src/main/java/cz/mzk/editor/client/view/ModifyView.java#L1100:L1104
https://github.com/moravianlibrary/MEditor/blob/master/editor-common/editor-common-client/src/main/java/cz/mzk/editor/client/view/other/EditorDragMoveHandler.java
Override BaseWidget.setDragTracker and provide required content using EventHandler.setDragTracker.
VLayout vLayout1 = new VLayout() {
#Override
protected boolean setDragTracker() {
EventHandler.setDragTracker("<pre>Drag to Lineup</pre>");
return false;
}
};
vLayout1.setCanDrop(true);
vLayout1.setCanDrag(true);
vLayout1.setDragAppearance(DragAppearance.TRACKER);
EventHandler.setDragTracker accepts any valid html code and <pre/> tags were used above to avoid word wrap.
Check following sample in SmartGWT showcase:
http://www.smartclient.com/smartgwt/showcase/#effects_dd_tracker

How to force GWT to add unique ID to each DOM element?

I am having a GWT app,
I would like to add ID to each element automaticlly
if it's impossible, what would be the fastest way to do it manually?
I am not so sure about performance issues. How would adding a dew ids in a form of 10-20 widgets cause performance loss?
To automagically set debug ids on widgets you need to include following in your module.gwt.xml file.
<!-- Enable debug ID. -->
<inherits name="com.google.gwt.user.Debug"/>
<set-property name="gwt.enableDebugId" value="true"/>
You can create your own Widget class that extends GWT Widget and sets an id to each one:
public class myWidget extends Widget {
public myWidget(String id) {
super();
getElement().setId("id");
}
public void setId(String id) {
// Use this method if you use Ui:Binder
getElement().setId("id");
}
}
You can, obviously, extend other classes instead of Widget if you don't need id on all widgets, like FlowPanel, Button, etc.
If you want to have an element to have an Id always, you can go with ensureDebugId of UI Object class. It make sure that, your element have an Id set before attaching it to the dom.
Yes its Possible :
First way:
Button b = new Button();
DOM.setElementAttribute(b.getElement(), "id", "my-button-id")
Second way :
FlowPanel panel = new FlowPanel();
panel.getElement().setId("my-flowpanel-id");
If you want to do assign all the id's attached to DOM you can do
Iterator<Widget> iterator = RootPanel.get().iterator();
while(iterator.hasNext()) {
Widget w = iterator.next();
w.getElement().setId("id");
}

calling a child page component from parent page component in wicket

I have a problem which I tried to explained in the Image.I hope that will help all to understand what I need.
My Base Page is like this (menuNavPanel is the tree panel):
<div class="colContainer">
<div class="leftColumn" >
<div wicket:id="menuNavPanel"></div>
</div>
<div class="rightColumn">
<wicket:child/>
</div>
</div>
And Ny BIA Page which is a child of Base Page is like this:
<wicket:extend>
<div wicket:id="bodyPanel"></div>
</wicket:extend>
in my Tree Panel, when I click on a node the code is this:
#Override
protected void onNodeLinkClicked(AjaxRequestTarget target, TreeNode node) {
super.onNodeLinkClicked(target, node);
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)node;
Unit unitObject =(Unit) treeNode.getUserObject();
// I want to call bodyPanel fo child page passing the unitObject param
}
Now, How can I call bodyPanel fo child page passing the unitObject param from the tree panel of the parent page?
Am I been able to express my problem? Hoping to get some help :)
Instead of doing the override method, upgrade to Wicket 1.5 and utilize the new event bus to communicate between your components. You can create a custom, type-safe, event that is specific to your component's use case: for example "ItemAddedToShoppingCart" or "GlobalThermoNuclearWarStarted".
The linked article in the 1.5 migration guide provides enough information on how to set up things.
I'm not sure I understand que question correctly. Your BasePage defines a left column with the TreePanel and lets subclasses expand themselves inside the right column div. You usually put a BodyPanel inside BasePages's subclasses. And now you want to invoke a BodyPanel's method on some event on the TreePanel.
You could do it with an overridable method on BasePage, which would be called in TreePanel through getPage(). Your child pages would override that method, and its implementation would call the BodyPanel they're holding.
public class BasePage ... {
// Hook
public void treePanelSelected(Object someObject) { }
...
}
public class ChildPage extends BasePage ... {
BodyPanel bodyPanel;
#Override
public void treePanelSelected(Object someObject) {
bodyPanel.selectionChanged/(someObject);
}
...
}
public class TreePanel ... {
...
#Override
protected void onNodeLinkClicked(AjaxRequestTarget target, TreeNode node) {
super.onNodeLinkClicked(target, node);
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)node;
Unit unitObject =(Unit) treeNode.getUserObject();
((BasePage)getPage()).treePanelSelected(unitObject);
}
}
From my ignorance on your specific needs and details of implementation, I don't see why is subclassing the BasePage necessary. You could add the BodyPanel right there in the BasePage and control it from the same class.
Thanks all, After reviewing all the nice options I finally opted out for the event bus way defined by martijn. What I did is I have created an event payload and connected the panels for the talking. I also needed to pass the selected Id / entity to the receiving panel.
Is there a way to set a compound property model of the receiving panel according to the model of the tree element so that I don't need to do the model manually ?
I did like this for the time being:
public class TreeNodeClickUpdate {
private final AjaxRequestTarget target;
private final long selectedId;
/**
* Constructor
*
* #param target
* #param selectedId
*/
public TreeNodeClickUpdate(AjaxRequestTarget target, long selectedId)
{
this.target = target;
this.selectedId = selectedId;
}
/** #return ajax request target */
public AjaxRequestTarget getTarget()
{
return target;
}
public long getSelectedId() {
return selectedId;
}
}
On the sender side I've done like this:
send(getPage(), Broadcast.BREADTH,
new TreeNodeClickUpdate(target, unitObject.getId()));
And on the receiving end I got it like this:
#Override
public void onEvent(IEvent<?> event) {
super.onEvent(event);
if (event.getPayload() instanceof TreeNodeClickUpdate)
{
TreeNodeClickUpdate update = (TreeNodeClickUpdate)event.getPayload();
setSelectedId(update.getSelectedId()); //sets to id field of panel
update.getTarget().add(this);
}
}
and for just as an example in my receiving panel, to get the value I have created a label like this:
label = new Label("label",new PropertyModel<BiaHomePanel>(this,"selectedId"));
Later, in reality I want to get information from the entity and show in form. Is there a nice way to pass models in a better way or I should pass as a parameter in event payload.
There are two ways to do this. One is cleaner, but requires more code. The other is quick and dirty.
Method 1: (Good)
Since your parent page is being extended, you can provide an abstract method in the parent like
protected abstract WebMarkupContainer getBodyPanel();
that is implemented in your child page and returns the appropriate panel. Then, you can call that method from the panel in your parent page. This is similar to the overrideable method suggested by the other user.
Method 2: (Bad)
The Wicket Component Hierarchy is shared between the parent and child pages. So, if you make sure that your bodyPanel has a unique wicketId and is added directly to the root of the page, you can probably just call
get("bodyPanelId");
and it will return the proper panel.
When I was facing the problem, I thought of two ways to solve this (pre 1.5):
a) implement a variation of the observer pattern to notify other component of events like outlined here: Realising complex cross-component ajax actions in wicket - The observer way
b) using wicket visitors to traverse the component tree doing the same.
I decided to go for variant a) but this introduces coupling from your component to your page-implementation which leads to problems when testing panels on their own. So maybe b) might be the better idea but since my application is running quite smoothly with a) implemented and the next big step will be switching over to 1.5 and the event bus, I haven't yet tried b).