Autocomplete and browse for a RelationChoice field are not working in a tile - autocomplete

I have a tile with a RelationChoice field, but the field just has the static html form elements (a "nothing" radio button, a text input and a 'Search' button), and it does not respond dynamically. In comparing it with an identical tile on another site that works, I noticed that the field-specific js code from plone.formwidget.contenttree and plone.formwidget.autocomplete is not embedded in the tile source. I put breakpoints in https://github.com/plone/plone.formwidget.autocomplete/blob/master/plone/formwidget/autocomplete/widget.py#L142 and in https://github.com/plone/plone.formwidget.contenttree/blob/master/plone/formwidget/contenttree/widget.py#L253, and they are getting hit when the tile loads, and the proper js is being returned. But I don't know why it doesn't get sent to the client.
Any ideas?
Everything else on the tile works fine, and the standard jquery resources are loaded:
++resource++plone.formwidget.autocomplete/jquery.autocomplete.min.js
++resource++plone.formwidget.autocomplete/formwidget-autocomplete.js
++resource++plone.formwidget.contenttree/contenttree.js
Here is the zcml for my tile:
<plone:tile
name="peps.tiles.calltoaction"
title="PEPS call to action tile"
description="A tile containing a full-size link, enclosing plain text"
add_permission="cmf.ModifyPortalContent"
schema=".tile.ICallToActionData"
class=".tile.CallToActionTile"
template="templates/calltoaction.pt"
permission="zope2.View"
for="*"
/>
And here is the tile schema and class:
class ICallToActionData(IRichTextTileData):
target = RelationChoice(
title=_(u"Link target"),
description=_(u'Choose the item to which this button will link'),
source=UUIDSourceBinder(),
required=False,
)
link_text = Text(
title=_(u"Link button text"),
description=_(u"The text for the link button at the bottom"),
)
class CallToActionTile(RichTextTile):
def target_url(self):
url = None
if self.data['target']:
obj = uuidUtils.uuidToObject(self.data['target'])
if obj is not None:
if obj.portal_type == "Link":
site_url = getToolByName(obj, 'portal_url')()
if not obj.getRemoteUrl().startswith(site_url):
url = obj.getRemoteUrl()
else:
url = obj.absolute_url()
return url
def link_text(self):
return self.text_value('link_text')
Plone 4.2.5
plone.app.tiles 1.0.1
plone.formwidget.contenttree 1.0.6
plone.formwidget.autocomplete 1.2.4

The cause of the problem were these Diazo rules:
<drop css:content="body script" />
<after css:theme-children="html body" css:content="html body script" method="raw" />
If a Diazo theme is active, it's always a good idea to deactivate it when debugging issues.

Related

Quasar2 Vue3 Cypress q-popup-edit

I have the following vue template:
<template>
<q-item tag="label" v-ripple>
<q-popup-edit
v-model="model"
:cover="false"
fit
buttons
:validate="validate"
#before-show="modelProxy = model"
>
<template v-slot:title>
<div class="text-mono">
{{ name }}
</div>
</template>
<q-input
color="indigo"
v-model="modelProxy"
dense
autofocus
counter
:type="dataType ? dataType : 'text'"
:hint="hint"
:error="error"
:error-message="errorMessage"
/>
</q-popup-edit>
<q-item-section>
<q-item-label class="text-mono">{{ name }}</q-item-label>
<q-item-label v-if="offset && model && model.length > offset" caption
>...{{
model.substring(model.length - offset, model.length)
}}</q-item-label
>
<q-item-label v-else caption>{{ model }}</q-item-label>
</q-item-section>
</q-item>
</template>
I would like to perform E2E test using Cypress with the following code snippet:
it('Verify Edit Box from auto-generated page', () => {
cy.get('[data-test="popup-edit-setting-1"]').contains("Auto Generated Edit box");
cy.get('[data-test="popup-edit-setting-2"]').contains("Auto Generated Edit box (Number)");
cy.get('[data-test="popup-edit-setting-1"]').should("be.enabled"); // XXX
cy.get('[data-test="popup-edit-setting-1"]').focus().click().type("Hello");//.click("SET");
cy.get('[data-test="popup-edit-setting-1"]').find("label").should('have.value', 'Hello') // XXX
});
It stumbles on the XXX points.
#Fody's solution works but there is one minor issue. I have 2 popup edit box. One with normal string, another with only numeric. There are 2 test cases for the numeric popup editbox. One with invalid normal string entry and another with valid numbers. The problem is that at the end of the test, the numeric popup edit box does NOT return to display mode. It stays popup.
This is the way I would test q-popup-edit. I used a generic example, yours may differ in some details.
I aimed to test based on what a user sees rather than any internal class or internal properties.
The user story is:
the text to be edited has a "hand" pointer when hovered
click on it to change it from "display" mode to "edit" mode
the input is automatically focused, user can start typing
user enters some text
user clicks away and the input loses focus, goes back to "display" mode
// activate popup editor
const initialText = 'Click me'
cy.contains('div.cursor-pointer', initialText) // displayed initial text
.should('be.visible') // with hand cursor
.click()
// initial condition
cy.focused() // after click <input> should have focus
.as('input') // save a reference
.should('have.prop', 'tagName', 'INPUT') // verify it is the input
cy.get('#input')
.invoke('val')
.should('eq', initialText) // displayed text is also in the input
cy.contains('8').should('be.visible') // character count
// edit action
cy.get('#input')
.clear()
.type('test input')
cy.get('#input')
.invoke('val')
.should('eq', 'test input') // verify input
cy.contains('10').should('be.visible') // character count has changed
// back to display mode
cy.get('body').click() // go back to display mode
cy.contains('div.cursor-pointer', 'test input')
.should('be.visible')
.and('contain', 'test input') // verify display element
cy.contains('10').should('not.exist') // edit counter has gone
Notes
To start the edit, you need to identify the display-mode element. It's easiest if you have some unique text in the field, so try to arrange that in the page initial data.
If no unique text, look for a label or some other selectable element nearby then navigate to it.
If you add a data-cy attribute to the <q-popup-edit>, it will not exist in the DOM until the component enters edit-mode (so you can't use it in the initial click()).

Accordion dropdown filtering through ion search bar

Hi I just created the ionic accordion dropdowns by following a tutorial blog link which used widgets for creating an accordion dropdowns, Below is the link of that blog.
http://masteringionic.com/blog/2019-01-27-creating-a-simple-accordion-widget-in-ionic-4/
updated: here is the my project demo link https://stackblitz.com/github/dSaif/search-accordion
Everything is working perfect, but i want to add Ion-searchbar at the top of the accordions sothat the dropdowns gets filter by inputing text.
please assist me how can i do that. Thank you.
You are going to have to create a variable in your homepage to store your filtered results. Then you need to have a filter function that will take the input from the search bar and filter your master list. Keep in mind you should not set the new variable to the master list, this could cause issues due to object referencing.
So you should have something like
in your html
<ion-searchbar placeholder="Search a name." [(ngModel)]="searchValue" (ionChange)="filterList()"></ion-searchbar>
In your ts file
searchValue: string = '';
filteredList: Array<{ name: string, description: string, image: string }> = this.technologies;
// function called in the html whenever you change the ion searchbar value
private filterList(){
//Make a variable so as to avoid any flashing on the screen if you set it to an empty array
const localFilteredList = []
this.technologies.forEach(currentItem => {
//here goes your search criteria, in the if statement
if(currentItem.name && currentItem.name.toLowerCase().includes(this.searchValue.toLowerCase())) {
localFilteredList.push(currentItem);
}
});
//finally set the global filter list to your newly filtered list
this.filteredList = localFilteredList;
}
You also need to make sure to reference the filterList variable instead of the current one you are referencing.

Replace HTML in response using Fiddler

I want to do something as simple as changing a color code in the response of an HTTP request, but I can't seem to figure it out. Basically, when a certain website loads, The background is set with the color code "#db4437" and I'd like to have it always be changed to "#09C3FF" when the website loads.
I found this code for Fiddlerscript in the Fiddler guides, but it doesn't seem to really do anything at all
if (oSession.HostnameIs("www.bayden.com") &&
oSession.oResponse.headers.ExistsAndContains("Content-Type","text/html")){
oSession.utilDecodeResponse();
oSession.utilReplaceInResponse('<b>','<u>');
}
This example from Telerik documentation works for me:
Remove all DIV tags (and content inside the DIV tag)
// If content-type is HTML, then remove all DIV tags
if (oSession.oResponse.headers.ExistsAndContains("Content-Type", "html")){
// Remove any compression or chunking
oSession.utilDecodeResponse();
var oBody = System.Text.Encoding.UTF8.GetString(oSession.responseBodyBytes);
// Replace all instances of the DIV tag with an empty string
var oRegEx = /<div[^>]*>(.*?)<\/div>/gi;
oBody = oBody.replace(oRegEx, "");
// Set the response body to the div-less string
oSession.utilSetResponseBody(oBody);
}

Using dojo dom.byId is not getting an element added programmatically

I'm creating a dom element programatically using dojo and I can "see" it in the dom with its id, but when I attempt a dom.byId("myId") it returns null.
I have a similar jsfiddle that is actually working (so it doesn't reproduce my problem, but it gives an idea of what I'm trying to do): if you click the button (ignore the lack of styling) in the run output panel, it alerts the content of the element retrieved by dom.byId. But similar code within my dojo widget is not working. Here's the code:
var content = lang.replace(selectFilterTemplate, {
"layer-id": layer.id,
"layer-index": idx,
"filter-name": filter.name
}); // this gets template HTML code similar to what's in the HTML panel of the jsfiddle, only it has placeholder tags {} instead of literals, and the tags are replaced with the attributes of the layer, idx, and filter objects here
// Use dojo dom-construct to create a div with the HTML from above
var node = domConstruct.create("div", { "innerHTML": content });
// put the new div into a dojo ContentPane
var filterPanel = new ContentPane({
"id": layer.id + "-filter-" + idx + "-panel",
"content": node,
"style": "width: 200px; float: left;"
});
// Get the dom element:
var mstag = dom.byId(layer.id + "-filter-" + idx + "-ms-tag")
// this is the same as the "var ms = dom.byId("IssuePoints-filter-1-ms-tag")" in the jsfiddle, but this one returns null. If I view the contents of the 'node' variable in the browser debugging console at this point, I can see the <select> tag with the id I'm referencing.
Why would I be getting null in my dom.byId() if I can see that element in the dom in the debugging console?
It seems that the element is added to the dom at a later point. You may see it with the debugger but it is not yet available the moment you call byId().
In the code you posted you create the filterPanel element but you do not place it in the dom. I assume this happens at a later stage. In contrast, the jsfiddle places the Button element with placeAt() directly after constructing it.

Lift CometActor: Organizing HTML generated by render and fixedRender

I'm trying to build a simple search application as an learning experiment with Comet and the Lift Framework. The plan is to have a page with a text entry and space for search results. When a search term is entered, it should be transmitted as an ajax request and the results should be pushed back by the server and rendered on the same page. When the server finds more results, they should be pushed to the client.
Using the Comet Chat Demo as template, I have a CometActor that renders both an ajax form and the search results from the following template:
<lift:comet type="SearchResults" name="Other">
<search:input><search:input /><input type="submit" value="Search" /></search:input>
<search:results>
<div>Results for: <search:tag /></div>
<div class="search-results">
<search:list>
<li><list:title /></li>
</search:list>
</div>
</search:results>
</lift:comet>
The corresponding SearchResults actor renders this in two parts: fixedRender generates the ajax form and render is responsible for rendering the search results.
class SearchResults extends CometActor {
override lazy val fixedRender: Box[NodeSeq] = {
SHtml.ajaxForm(bind("search", findKids(defaultXml, "search", "input"),
"input" -> SHtml.text("", updateSearch _)))
}
private def updateSearch(tag: String) = Log.info("UpdateSearch: " + tag)
def render = {
bind("search", findKids(defaultXml, "search", "results"),
"tag" -> "MyTag", // TODO show actual search tag
"list" -> <ul><li>Entry</li></ul>) // TODO actual search results
}
}
In principle this code works, but it renders the search box below the results not on top where I would expect it.
I assume, this has to do with the oder in which render and fixedRender are executed. How can change this code to have the search box at the top?
Have a look at CssSelectors. But i guess this question is obsolete by now ;) Also CssSelectors weren't available back in 09.