Rails 3, using UJS on html area tag - ajax

When the user clicks on on area of an image I want to trigger and ajax request to the server. Is there an easy way to implement this a-la Rails 3 UJS? Something similar to link_to ..., :remote=>true?
I have tried to the following code:
#post_bar
=image_tag 'post_bar_270x57.png', :usemap=>'#add_post'
%map{:name=>"add_post"}
%area{:shape=>"rect", :coords=>"40,4,86,50", :href=>new_message_path, :'data-remote'=>'true', :title=>"Message"}
but the added data-remote attributes does not work.
Thanks for any help.

After trying several things I concluded the easiest way is to to have an HTML anchor element on top of the png with that I can simply use the link_to helper with :remote=>true.
It took me less than 10 minutes to get the all thing working.
Edit: here is the code form my haml file (in production I removed the map element)
#post_bar
=image_tag 'post_bar_270x57.png', :usemap=>'#add_post'
%map{:name=>"add_post"}
%area{:shape=>"rect", :coords=>"40,4,86,50", :href=>new_message_path, :title=>"Message"}
%area{:shape=>"rect", :coords=>"100,4,146,50", :href=>new_message_path, :title=>"Reminder(140 chars)"}
#post_message_link
=link_to "", new_message_path, :remote=>true
and the css
#post_message_link a{
position: absolute;
top: 0px;
left: 40px;
width: 45px;
height: 50px;
display: block;
z-index: 100;
}

In the jquery-rails gem (path found with 'bundle show jquery-rails') there is a javascript file for jquery-ujs under vendor/assets/javascripts.
On line 51 you can see the following:
// Link elements bound by jquery-ujs
linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote], a[data-disable-with]'
I found adding the area tag to this line allows you to use UJS in the same way as you do for normal links, etc.
Ideally, you would make the code a bit better by adding another variable, but since this is just a hack I added it to the existing variables.
// Link elements bound by jquery-ujs
linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote], a[data-disable-with]', 'area[data-confirm]', 'area[data-method]', 'area[data-remote]',

Related

Is there a way to freeze a column in a vuetify data table?

I cannot find a good solution to this without using a vuetify fork, which isn't stable and appears to be the older version anyway. I will link to it in the comments.
The only way I can think to do this is to line up two data tables side by side, which creates problems in itself. I know there are other plugins/libraries that allow this, but I would really prefer to stick with vuetify. Has anyone had success with doing this?
My project is to create a grid that allows the user to set up a rotation. Each column (after the first one) is a dynamically created week (Friday's date is column header) that shows if there is an opening in a given organization. The struggle is to get enough weeks to show up on the screen at once. The first column is the organization. So, I want to know what organization my row is in for a given week as I scroll to the right. That's why I need to freeze the first column.
I'm open to other solutions - like a different way to show the header, perhaps, that would allow me to fit in 52 weeks worth of dates.
I am also searching for a solution to this. The nearest I have found is this complex bit of CSS Source
<style>
table > tbody > tr > td:nth-child(1),
table > thead > tr > th:nth-child(1) {
position: sticky !important;
position: -webkit-sticky !important;
left: 0;
z-index: 9998;
background: white;
}
table > thead > tr > th:nth-child(1) {
z-index: 9999;
}
</style>
However, it doesn't quite work for my case.
I have something like this
Account Jan Feb Mar
123456 50 51 52
123458 38 39 32
123600 20 21 22
So what I am looking for is the Excel equivalent of putting a freeze panes on the Jan,123456 intersection, so that the months stay in place when scrolling down, and the Account column stays in place when scrolling to the right.
I set the fixed-header and :height property on the v-data-table so that the header does not scroll vertically and so that it has a vertical scroll bar. The horizontal scroll bar seems to happen automatically and is specific to the table rather than the page.
Without the CSS the vertical scrolling works, though obviously not the horizontal scrolling as the Account column scrolls off screen to the left.
With the CSS the account numbers stay in position, but the headings still scroll to the left, so eg Jan replaces Account. Also when scrolling down, the Account Numbers scroll up to overwrite Account. It is closer to a solution than the basics provided by Vuetify.
I also saw the example from someone who had cloned vuetify and modified it to include fixed columns and grouping. However, I was not sure whether that was vuetify 1.5 or 2 and I have already had issues with seeing examples on 1.5 and then finding that they don't work on vue 2 which I am using as there were so many breaking changes. Like you I am also wary of adopting something that may not be supported.
I am surprised that Vuetify did not include this. It must be a pretty common requirement. I have seen an enhancement request for Vuetify 3, but it is too early to adopt that and presumably it would also mean adopting Vue 3.
Regards
Paul Simon
I finally found an approach to this that works. Another approach
However, I cannot really claim it as an answer to the original question as it only works by abandoning the use of a v-data-table altogether. I ended up just putting a standard table in between v-spacer in my vuetify card. Any attempt to use even a v-simple-table added a second unnecessary horizontal scroll bar which ruined the effect.
The bit of CSS linked above does at least give fixed header(s) and fixed column(s) with none of the issues around scrolling up over the top left corner cell of other approaches I have seen.
It is also very easy to mark which headers you want fixed (usually all) and, in particular, which columns you want fixed. Note that the fixed columns should use 'th' rather than 'td'. This is ideal for my purpose since my data source is multi-dimensional and returns row headers and then cells with numbers eg
Actual Actual Budget Budget
Country Product Jan Feb Jan Feb
UK Widget1 50 60 70 20
UK Widget2 60 80 90 100
USA Widget1 90 80 10 90
In the example above all the following are 'th'
Actual, Budget, Jan, Feb
Country, Product
Only the number cells are 'td'
As you can see, all you need to do is to mark the 'th' in the html with class="fixed" so unlike other approaches it works for an arbitrary number of columns rather than just the left most column.
I am an expert in multi-dimensional modelling, and certainly not an expert in CSS, but I modified the CSS in the linked example a little. My CSS is as follows:
<style scoped>
.table {
background-color: white;
margin: auto;
width:90%;
max-width:100%;
border-collapse: separate;
display: block;
overflow-x: scroll;
}
thead,
tbody {
display: inline-block;
}
thead {
position: sticky;
top: 1px;
z-index: 2;
}
tbody {
height: 200px;
}
th {
background-color: lightgrey;
border-left: 1px;
border-right: 1px;
border-color: black;
}
td,
th {
min-width: 100px;
max-width: 100px;
word-wrap: break-word;
}
.fixed {
position: sticky;
width: 5em;
left: 0;
top: auto;
z-index: 1;
}
td:not(.fixed) {
z-index: 0;
}
</style>
Instead of giving a fixed width for the table, I used %. I know that not all browsers support this but this is going to be an internal application. It is not a shopping site.
I also took the z-indexes down from 9999,999,0 to 2,1,0 as without this it tended to wind up on top of the Vuetify footer when scrolling down.
Regards
Paul Simon

Vuetify-DataTable Change Header Height

I am trying to change the height of the Table header unfortunate an not able to find any way to change table header height.
Could you please help me to reduce the table header height?
I have attached the screen shot.
For everyone who stumbles across this question:
You can change the header height or basically every css attribute of the header via css.
Just add this piece of code to your <style> tag
<style>
>>> .v-data-table-header {
height: 70px;
}
</style>
You can do it only with CSS. Maybe in version 2 it will be done.
Today set style on selector table.v-table thead tr {}
'v-data-table' API option
your variables.scss input variable
v-data-table
$data-table-regular-header-height: 2rem;
v-data-table option dense
// all table height(v-data-table option dense)
$data-table-dense-header-height: 2rem;
only table header height, modify '$data-table-dense-row-height'
// basic value
$data-table-dense-row-height: data-table-dense-header-height !default;
other sass option -> vutify site

Selector fails to find ins on page

I have a funky element on an html page that I am having trouble selecting with an XPath query. I am using Capybara, however I hope this is an XPath problem. Possibly the - character needs escape or bad query?
HTML Element
<ins class="iCheck-helper" style="position: absolute; top: 0%; left: 0%; display: block; width: 100%; height: 100%; margin: 0px; padding: 0px; border: 0px; opacity: 0; background: rgb(255, 255, 255);"></ins>
XPath
"//*[contains(#class, 'iCheck-helper')]"
Ruby/Capybara
elements = all(:xpath, myXPathQuery) (documentation)
elements.Count is a Capybara::Result. elements.count returns 0 and I expect 1.
Is there a specific reason you need to do this as XPath? Capybara supports CSS selectors which are much easier to write for class names.
elements=all(:css, '.iCheck-helper')
Also when using all it returns immediately by default since it assumes no elements is a valid result. If your page is dynamically changing and you know you are want at least one element you should do
elements=all(:css, '.iCheck-helper', minimum: 1)
which will wait up to Capybara.default_wait_time seconds for at least one matching element to appear. You could also pass count: 1 (instead of minimum) if you know for sure you only want one element and any more than that should be an error, although in that case #find probably makes more sense
I have just noticed your CSS which is scrolled off to the right which has opacity: 0 - In any of the real browser drivers (selenium, capybara-webkit, poltergeist, etc - basically anything but racktest) that will make the element invisible so it will not be found by default. To find that element you can do
elements=all(:css, '.iCheck-helper', minimum: 1, visible: :all)
Please note that since Capybara is meant to emulate a real user, finding invisible elements is usually not a good thing since a real user couldn't see it or interact with it. Its generally a better idea to perform whatever action would make that element visible and then check for its existence/interact with it.
Try:
myXPathQuery = '//ins[#class="iCheck-helper"]'
elements = all(:xpath, myXPathQuery)

css: set image-width inside of paragraph with specific width?

hey guys,
somehow i can't find the solution for my little problem.
i have a paragraph setting with a max-width of 630px.
in some cases i have images within one of those paragraphs - and in this case i want the image to act normal -> without any max-width setting.
.post-body p {
width:99%;
max-width: 630px;
}
.post-body p img{
max-width:100% !important;
}
is it even possible to have the image larger than the max-width setting that's set to it's parent? do i need to use javascript (jquery)?
thank you for your help.
Unless you're modifying the image width some other way, as long as you don't do anything to the image it will display at full size.
See here: http://jsfiddle.net/WrfQQ/
I didn't bother declaring any CSS for the image, so it, by default, will show up at full size. (Please note, for the sake of testing I decreased the width of the p to 100px)
As I can see the problem is that you put a MAX-width to the img... you have to code the relative width... so:
.post-body p img{
position: relative;
width: 100%;
}
if you want it in jQuery the code is the below:
$('.post-body p img').width() == $('.post-body p').width();

Using CSS max-height on an outer div to force scroll on an inner-div

I have an outer div with a variable height (and max-height) that's set with a specific pixel amount by JavaScript, containing two divs within.
The 1st div is intended to hold a variable amount of content, e.g. a list of links. It has no height set.
The 2nd div is intended to hold a fixed amount of content, and has a specific height set.
Right now, the max-height isn't working. The 1st div keeps growing, even with overflow: auto; set, and pushes the 2nd div below it outside the bounds of the outer div. How can I make it so that when the 1st div gets too large for the outer div to contain both it and the fixed-height 2nd div, the 1st div will start to scroll?
Example page: http://thevastdesign.com/scrollTest.html
Thanks for any help. I'd appreciate a CSS solution the most, even if it requires some hacks. It only has to work in Firefox 3+, IE8, and IE7.
Ideas?
You cant really do that without JS. Your max-height on the outer-div isnt going to control the height of one of your inner divs to invoke its scrolling. That inner div is always going to be the height you set (pixels, auto, etc..). You can either make the entire outer div scroll as needed by using overflow: auto or you can set a max height on the first inner div and set the overflow.
Given your setup, I would do the following (class names are implied by your question, not taken from the linked source):
div.outer {
position: relative;
max-height: $length(y);
overflow: hidden;
}
div.innerFixed {
position: absolute;
bottom: 0;
height: $length(y);
overflow: hidden; /* just in case, to keep things from
blowing out into all manner of crazy */
}
div.innerFlex {
max-height: $length(y);
overflow: auto;
}
These rules don't address box properties, which will have an impact on the height values that you apply. The combined height values (with box values included) of .innerFixed and .innerFlex should equal the height value of the container.
If you want to get all Zen and flip the vertical composition, you do that by swapping bottom for top on .innerFixed and assigning margin-top or padding-top to .innerFlex.
Something else I noticed is that you've got
div.outer { float: left; }
...But given what you need from that element (and to set the right content priority) I would instead suggest that you put your big column first in the source order and apply
div.mainContent {
float: right;
width: $length(x);
}
div.outer { /* i.e., the column that started the discussion */
margin-right: length(x);
}
with the understanding that the margin-right of the latter is somewhat greater than the width of the former (greater to account for the gutter between the two elements). Try it, you'll like it.

Resources