jqgrid 2 span elements within one custom cell? - jqgrid

Within my custom cell there are 2 span-elements.
<span class="FormElement">
<span class="customelement" id="code" name="code">BER01_CN_045_002</span>
</span>
Is there a way to avoid this?
See the demo, I am talking about cell "code".

I think, that you should don't spend your time in such kind of code optimization. Like I tried to explain in my previous answer the first <span> will be inserted by jqGrid for all form elements having the option edittype:'custom'. The second <span> you inserted yourself in the code of your custom formatter. It is permitted to have nested <span> elements like to have nested <div> elements. I recommend you better to follows the jqGrid standard code as trying to make any kind of optimization which nobody will see at the end except you.
Moreover if you look more in the HTML code of your page generated by jqGrid you will see that the form itself (the form with id="FrmGrid_grid" in your example) are placed inside of <span>. In the same way in the code of the column headers you will also find <span class="s-ico"> which has another two <span> elements as the children. Would you like to try to "optimize" also the code? So I repeat my advice just to hold jqGrid standards and not trying to optimize such small pieces of code like nested <span> elements.

Related

XPath: How do I find a page element which contains another element, using the full text of both?

I have an HTML page which contains the following:
<div class="book-info">
The book is <i>Italicized Title</i> by Author McWriter
</div>
When I view this in Chrome Dev Tools, it looks like:
<div class="book-info">
"The book is "
<i>Italicized Title</i>
" by Author McWriter"
</div>
I need a way to find this single div using XPath.
Constraints:
There are many book-info divs on the page, so I can't just look for a div with that class.
Any part of the text within the book-info div might also appear in another, but the complete text within the div is unique. So I want to match the entire text, if possible.
It is not guaranteed that an <i> will exist within the book-info div. The following could also exist, and I need to be able to find it as well (but my code is working for this case):
<div class="book-info">
"Author McWriter's Legacy"
</div>
I think I can detect whether the div I'm looking for contains an <i> or not, and construct a different XPath expression depending on that.
Things I have tried:
//div[text()=concat("The book is ","Italicized Title"," by Author McWriter")]
//div[text()=concat("The book is ","<i>Italicized Title"</i>," by Author McWriter")]
//div[text()=concat("The book is ",[./i[text()="Italicized Title"]," by Author McWriter")]
//div[concat(text()="The book is ", i[text()="Italicized Title"],text()=" by Author McWriter")]
None of these worked for me. What XPath expression would?
You can use this combination of XPath-1.0 predicates in one expression. It matches both cases:
//div[#class="book-info" and ((i and contains(text()[1],"The book is") and contains(text()[2],"by Author McWriter")) or (not(i) and contains(string(.),"Author McWriter&apos;s Legacy")))]

I have doubts about two mappings on the site-prism

I don't want to use xpath on the elements below.
element :img_login, :xpath, '//[#id="main-wrapper"]/div/section/div/div[2]/div/div/div[1]/img'
element :msg_login_senha_invalidos, :xpath, '//[#id="main-wrapper"]/div/section/div/div[2]/div/div/div[2]/div/p'
They are on the page as follows:
element img_login
<div class="sc-jRQAMF eRnhep">
<img src="https://quasar-flash-staging.herokuapp.com/assets/login/flashLogo-3a77796fc2a3316fe0945c6faf248b57a2545077fac44301de3ec3d8c30eba3f.png" alt="Quasar Flash">
</div>
element msg_login_senha_invalidos
<p class="MuiFormHelperText-root MuiFormHelperText-contained Mui-error MuiFormHelperText-filled">Login e/ou senha inválidos</p>
You have asked multiple questions about converting from using XPath to some other type of selector when using Site-Prism. StackOverflow is meant to be a place to come, learn, and improve your skills - not just to get someone else to do your work. It really seems you'd be better off reading up on CSS and how it can be used to select elements. Also note that there's nothing specifically wrong with using XPath, per se, it's just the way people new to testing and selecting elements on a page tend to use it (just copying a fully specified selector from their browser) that leads to having selectors that are way too specific and therefore brittle. A good site for you to learn about the different general CSS selector options available is https://flukeout.github.io/ - and you can look at the built-in selector types provided by Capybara at https://github.com/teamcapybara/capybara/blob/master/lib/capybara/selector.rb#L18
In your current case the below may work, but with the HTML you have provided all that's possible to say is that they will match the elements shown however they may also match other elements which will give you ambiguous element errors.
element :img_login, :css, 'img[alt="Quasar Flash"]' # CSS attribute selector
element :msg_login_senha_invalidos, :css, 'p.Mui-error', text: 'Login e/ou senha inválidos' # CSS class selector combined with Capybara text filter

Can not input to EditableElement of CKEditor5

In CKEditor5, I tried implementing custom element to convert model to view for editing. Then, editable element(#ckeditor/ckeditor5-engine/src/view/editableelement) in container element(#ckeditor/ckeditor5-engine/src/view/containerelement) is focused on the parent container element and can not be edited.
For example, if it is implemented as follows:
buildModelConverter().for(editing.modelToView)
.fromElement('myElement')
.toElement(new ContainerElement('div', {}, [new EditableElement('h4')]));
The result of actual editing dom after inserting 'myElement' and keydown "abc". (I hope inputting text of "abc" to h4 tag but...)
<div>​​​​​​​
abc
<h4>
<br data-cke-filler="true">
</h4>
</div>
I also tried using widget for applying contenteditable attribute.
But, text couldn't be entered in h4.
<div class="ck-widget" contenteditable="false">​​​​​​​
<h4 class="ck-editable" contenteditable="true">
<br data-cke-filler="true">
</h4>
</div>
Is this bug, or I made mistake understanding of container element?
[Additional details]
I am assuming to make a widget plugin for ranking list.
First, the ranking list is structured by <ol> and <li> tags because of having multiple items.
I solved that by defining two schema such as "rankingList" and "rankingListItem",
so I realized dynamic elements using nested model elements.
const item1 = new ModelElement('rankingListItem');
const item2 = new ModelElement('rankingListItem');
const model = new ModelElement('rankingList', {}, [item1, item2]);
// and insert
Next, the item of ranking list has link, image, title and note.
Therefore, the ranking list item has the following DOM structure:
<ol><!-- apply toWidget -->
<li>
<a href="link[editable]">
<img src="image[editable]">
<h3>title[editable]</h3>
<p>notes[editable]</p>
</a>
</li>
...
</ol>
I expect the view element is the following:
const {ref, src, title, notes} = data; // how to get data?
const view = new ContainerElement('a', {ref}, [
new EmptyElement('img', {src}),
new EditableElement('h3', {}, new Text(title)),
new EditableElement('p', {}, new Text(title)),
]);
// maybe incorrect ...
In conclusion, I want to use editable view not to break defined DOM tree.
How can I realize it?
Thank you for describing your case. It means a lot for us at the moment to know how developers are using the editor and what are your expectations.
Unfortunately, this looks like a very complex feature. It also looks like it would need custom UI (to edit link url and image src -- unless they do not change after added to the editor). It seems that you struggle with two problems:
position mapping between the model and the view,
nested editables.
First, to answer your question about EditableElement - it seems to be correct to use them for h3 and p elements.
However, such complex feature needs custom converters. Converter builders (which you used) are dedicated to being used in simple cases, like element-to-element conversion, or attribute-to-attribute conversion.
Behind the nice API, build converter is a function factory, that creates one or multiple functions. Those are then added as callbacks to ModelConversionDispatcher (which editor.editing.modelToView is an instance of). ModelConversionDispatcher fires a series of events during the conversion, which is a process of translating a change in the model to the view.
As I've mentioned, you would have to write those converting functions by yourself.
Since this is too big of a subject for a detailed and thorough answer, I'll just briefly present you what you should be interested in. Unfortunately, there are no guides yet about creating custom converters from scratch. This is a very broad subject.
First, let me explain you from where most of your problems come from. As you already know, the editor has three layers: model (data), view (DOM-like structure) and DOM. Model is converted to view and view is rendered to DOM. Also, the other way, when you load data, DOM is converted to view and view is converted to model. This is why you need to provide model-to-view converter and view-to-model converter for your feature.
The important piece of this puzzle is engine.conversion.Mapper. Its role is to map elements and positions from model to view. As you already might have seen, the model might be quite different than the view. Correct position mapping between those is key. When you type a letter at caret position (in DOM), this position is mapped to model and the letter is inserted in the model and only then converted back to the view and DOM. If view-to-model position conversion is wrong, you will not be able to type, or really do anything, at that place.
Mapper is pretty simple on its own. All it needs is that you specify which view elements are bound to which model elements. For example, in the model you might have:
<listItem type="bulleted" indent="0">Foo</listItem>
<listItem type="bulleted" indent="1">Bar</listItem>
While in the view you have:
<ul>
<li>
Foo
<ul>
<li>Bar</li>
</ul>
</li>
</ul>
If the mapper knows that first listItem is bound with first <li> and the second listItem is bound with second <li>, then it is able to translate positions correctly.
Back to your case. Each converter has to provide data for Mapper. Since you used converter builder, the converters build by it already do this. But they are simple, so when you provide:
buildModelConverter().for(editing.modelToView)
.fromElement('myElement')
.toElement(new ContainerElement('div', {}, [new EditableElement('h4')]));
it is assumed, that myElement is bound with the <div>. So anything that is written inside that <div> will go straight to myElement and then will be rendered at the beginning of myElement:
<div>
<h4></h4>
</div>
Assuming that you just wrote x at <h4>, that position will be mapped to myElement offset 0 in the model and then rendered to view at the beginning of <div>.
Model:
<myElement>x</myElement>
View:
<div>x<h4></h4></div>
As you can see, in your case, it is <h4> which should be bound with myElement.
At the moment, we are during refactoring phase. One of the goals is providing more utility functions for converter builders. One of those utilities are converters for elements which have a wrapper element, like in that "div + h4" case above. This is also a case of image feature. The image is represented by <image> in model but it is <figure><img /></figure> in the view. You can look at ckeditor5-image to see how those converters look like now. We want to simplify them.
Unfortunately, your real case is even more complicated because you have multiple elements inside. CKE5 architecture should be able handle your case but you have to understand that this is almost impossible to write without proper guides.
If you want to tinker though, you should study ckeditor5-image repo. It won't be easy, but this is the best way to go. Image plugin together with ImageCaption are very similar to your case.
Model:
<image alt="x" src="y">
<caption>Foo</caption>
</image>
View:
<figure class="image">
<img alt="x" src="y" />
<figcaption>Foo</caption>
</figure>
While in your case, I'd see the model somewhere between those lines:
<rankItem imageSrc="x" linkUrl="y">
<rankTitle>Foo</rankTitle>
<rankNotes>Bar</rankNotes>
</rankItem>
And I'd make the view a bit heavier but it will be easier to write converters:
<li contenteditable="false">
<a href="y">
<img src="x" />
<span class="data">
<span class="title" contenteditable="true">Foo</span>
<span class="notes" contenteditable="true">Bar</span>
</span>
</a>
</li>
For rankTitle and rankNotes - base them on caption element (ckeditor5-image/src/imagecaption/imagecaptionengine.js).
For rankItem - base it on image element (ckeditor5-image/src/image/).
Once again - keep in mind that we are in the process of simplifying all of this. We want people to write their own features, even those complicated ones like yours. However, we are aware of how complex it is right now. That's why there are no docs at the moment - we are looking to change and simplify things.
And lastly - you could create that ranking list simpler, using Link plugin and elements build with converter builder:
rankList -> <ol class="rank">,
rankItem -> <li>,
rankImage -> <img />,
rankNotes -> <span class="notes">,
rankTitle -> <span class="title">.
However, it will be possible to mess it up because the whole structure will be editable.
Model:
<rankList>
<rankItem>
<rankImage linkHref="" />
<rankTitle>Foo</rankTitle>
<rankNotes>Bar</rankNotes>
</rankItem>
...
</rankList>
Where "Foo" and "Bar" also have linkHref attribute set.
View:
<ol class="rank">
<li>
<img src="" />
<span class="title">Title</span>
<span class="notes">Foo</span>
</li>
...
</ol>
Something like this, while far from perfect, should be much easier to write as long as we are before the refactor and before writing guides.
Of course you will also have to provide view-to-model converters. You might want to write them on your own (take a look at ckeditor5-list/src/converters.js viewModelConverter() -- although yours will be easier because it will be flat, not nested list). Or you can generate them through converter builder.
Maybe it will be possible to use the approach above (simpler) but use contentEditable attribute to control the structure. rankList would have to be converted to <ol> with contentEditable="false". Maybe you could somehow use toWidget for better selection handling, for example. rankNotes and rankTitle would have to be converted to element with contentEditable="true" (maybe use toWidgetEditable()).

geb: select by existence of attribute

Given the following html:
<a class="foo">
<a class="foo" href="somePonderousJSIDontWantToQuoteInMyTests">
One can select the later from the former using $("a.foo", href: ~/.*/).
Is there a more elegant way of selecting an element, based on whether or not it has a certain attribute?
Thanks!
I don't know if using a CSS3 attribute matcher is more elegant but it's definitelly quicker especialy if your selector would return many elements without the filter because the filtering happens in the browser and not in the jvm as in your approach:
$("a.foo[href]")

Want new divs to push down older divs dynamically

I have 3 divs parallel to each other holding some information. I want three new divs, in the same position as the previous ones (refer image), take the position of the last ones while pushing the same downwards.
I want this action to happen dynamically i.e. when someone enters information on the back-end module, the more recent information takes place of the older one.
I am pretty new to Ajax and jQuery but I am sure this is the way to go. Can someone please direct me to a suitable direction?
Image: http://img12.imageshack.us/img12/4149/us56.jpg
You are right, Ajax and jQuery can be the way to go.
Simplest solution is probably to put the three blocks into one div and call
$("#parent-div").prepend();
on it. You can arrange the blocks how you want using CSS
<div id='parent-div'>
<div class="col left">Hello World</div>
<div class="col">Hello World</div>
<div class="col">Hello World</div>
</div>
Tried it out on jsFiddle, just have a look.
http://api.jquery.com/insertBefore/
example:
$('<div>new div</div>').insertBefore('#divName');

Resources