Jquery combining show/hide with slideToggle script - slidetoggle

I have 2 scripts that I am using and I would like to combine them into 1 but I haven't been successful so I would appreciate some help if possible. The first script is a show/hide when pressing a Expand all and collapse all button:
$(".hide").click(function(){
$(".screentitle").hide();
});
$(".show").click(function(){
$(".screentitle").show();
});
The second code I use is the image swap for slideToggle:
$(".chaptertitle").live("click", function(){
$(".screentitle", this).slideToggle("fast");
var $img = $(".img-swap", this);
if ($img.attr('src').indexOf("plus.png") > -1) {
$img.attr('src', $img.attr('src').replace('plus', 'minus'));
return false;
} else {
$img.attr('src', $img.attr('src').replace('minus', 'plus'));

Related

Protractor locator issues

My goal is to pull the css width of a particular element.
The actual jQuery command I use in Chrome console works well :
$('div-grid-directive[grid-name="SAT"] .qMinus1_resize_expand').first().css('width');
"0px"
However, running Protractor in a Win 7 cmd prompt, I'm getting the following error:
Message:
Failed: element(...).first is not a function
The error points to my objects page topNav.icons.page.js, in this.getQMinus1Column :
module.exports = function(){
this.clickExpandRowsIcon = function(){
$('.resize-btns > .glyphicon.glyphicon-resize-horizontal').click();
browser.driver.sleep(2000);
};
this.getQMinus1Column = function(){
return element(by.css('div-grid-directive[grid-name="SAT"] .qMinus1_resize_expand')).first();
};
};
and my SAT.spec.js file :
var IndexPage = require('./pageObjects/index.page.js');
var TopNavBar = require('./pageObjects/topNav.icons.page.js');
describe('Testing the Sales & Trading Top Nav grid icons', function(){
var indexPage = new IndexPage();
var topNavBar = new TopNavBar();
beforeEach(function () {
indexPage.get(); // Launches app !!
});
describe('Clicking on the Expand Rows icon', function () {
it('Should horizontally expand previous quarters qMinus1 thru qMinus6', function () {
topNavBar.clickExpandRowsIcon();
var elem = topNavBar.getQMinus1Column();
expect(elem).getCssValue().indexOf('width: 5px;').not.toBe('-1');
});
});
});
So before I even try to get the css width attribute, I'm struggling to return first(), using this format:
return element(by.css('MY-CSS')).first();
Do I have too much going on in this line, or perhaps the wrong syntax for Protractor ?
return element(by.css('div-grid-directive[grid-name="SAT"] .qMinus1_resize_expand')).first();
Again, the same syntax works using jQuery in console tools, so the CSS select is correct.
Advice is greatly appreciated here...
regards,
Bob
As per this , element does not return a collection of objects to call first method in it.
Probably you might want to use element.all(locator)

kendo-ui autocomplete extend

I'm trying to extend the kendo-ui autocomplete control: I want the search start when te user hit enter, so basically I've to check the user input on keydown event.
I've tried to catch the keydown event with this code:
(function($) {
ui = kendo.ui,
Widget = ui.Widget
var ClienteText = ui.AutoComplete.extend({
init: function(element,options) {
var that=this;
ui.AutoComplete.fn.init.call(this, element, options);
$(this).bind('keydown',function(e){ console.log(1,e); });
$(element).bind('keydown',function(e){ console.log(2,e); });
},
options: {
[...list of my options...]
},
_keydown: function(e) {
console.log(3,e);
kendo.ui.AutoComplete.fn._keydown(e);
}
});
ui.plugin(ClienteText);
})(jQuery);
None of the binded events gets called, only the _keydown, and then I'm doing something wrong and cannot call the autocomplete "normal" keydown event.
I've seen a lot of examples that extend the base widget and then create a composite widget, but I'm not interested in doing that, I only want to add a functionality to an existing widget.
Can someone show me what I'm doing wrong?
Thank you!
What about avoiding the extend and take advantage of build in options and methods on the existing control : http://jsfiddle.net/vojtiik/Vttyq/1/
//create AutoComplete UI component
var complete = $("#countries").kendoAutoComplete({
dataSource: data,
filter: "startswith",
placeholder: "Select country...",
separator: ", ",
minLength: 50 // this is to be longer than your longest char
}).data("kendoAutoComplete");
$("#countries").keypress(function (e) {
if (e.which == 13) {
complete.options.minLength = 1; // allow search
complete.search($("#countries").val());
complete.options.minLength = 50; // stop the search again
}
});
This code actually work:
(function($) {
ui = kendo.ui,
ClienteText = ui.AutoComplete.extend({
init: function(element,options) {
ui.AutoComplete.fn.init.call(this, element, options);
$(element).bind('keydown',function(e){
var kcontrol=$(this).data('kendoClienteText');
if (e.which === 13) {
kcontrol.setDataSource(datasource_clientes);
kcontrol.search($(this).val());
} else {
kcontrol.setDataSource(null);
}
});
},
options: {
name: 'ClienteText',
}
});
ui.plugin(ClienteText);
})(jQuery);
but I don't know if it's the correct way to do it.

AngularJS: Move to next form input element after successful validation

I have written a custom directive for validation of my form fields. When certain criteria are met (i.e. it is dirty and valid), I want to set the focus automatically to the next input element. This is a requirement from my users, such that they can move through the forms most efficiently.
The simplified directive looks like this:
directive('custom', ['$parse', function($parse) {
return {
restrict: 'A',
require: ['ngModel', '^ngController'],
link: function(scope, element, attrs, ctrls) {
var model=ctrls[0], form=ctrls[1];
scope.next = function(){
return model.$valid
}
scope.$watch(scope.next, function(newValue, oldValue){
if (newValue && model.$dirty){
???
}
})
Now my question is: how can I identify
- the next input element (which is the next sibling) or possibly via the tabindex
- and focus on it
without using Jquery?
For me, it is currently not clear, how to get to the next input element from the available "scope" or "element" attributes without Jquery; and JQlite does nothave a "focus" method. Basically, I need a working substitute for ??? in my code.
Any help is highly appreciated. Thanks
Juergen
You can use [0] to get the underlying input element (which has a focus() function) from the angular/jqLite object (which doesn't).
app.directive('custom', ['$parse', function($parse) {
return {
restrict: 'A',
require: ['ngModel'],
link: function(scope, element, attrs, ctrls) {
var model=ctrls[0], form=ctrls[1];
scope.next = function(){
return model.$valid;
}
scope.$watch(scope.next, function(newValue, oldValue){
if (newValue && model.$dirty)
{
var nextinput = element.next('input');
if (nextinput.length === 1)
{
nextinput[0].focus();
}
}
})
}
}
}])
http://jsfiddle.net/Y2XLA/
element.next().focus() might not work if you have a complex form and input are nested into different divs.
I ended writing this directive (here I move the focus on Enter, but can be adapted to whatever event):
.directive('enterToTab', function($timeout) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var procAttr = 'data-ett-processed';
$timeout(function() { // Use $timeout to run the directive when the DOM is fully rendered
var formElements = element[0].querySelectorAll('input:not([' + procAttr + '="true"]), select:not([' + procAttr + '="true"]), textarea:not([' + procAttr + '="true"])');
// Run through all elements in form
var formElementsLength = formElements.length;
for (var i = 0; i < formElementsLength; i++) { // Add tabindex attribute
formElements[i].setAttribute('tabindex', i + 1);
// Go to next element on Enter key press
formElements[i].addEventListener('keypress', function(event) {
if (event.keyCode === 13) { // Enter
// Prevent Angular from validating all the fields and submitting
if (event.target.tagName !== 'TEXTAREA') { // Not on textarea, otherwise not possible to add new line
event.stopPropagation();
event.preventDefault();
}
var nextIndex = parseInt(event.target.getAttribute('tabindex')) + 1;
// Move focus to next element
// TODO: find next visible element
var nextElem = element[0].querySelector('[tabIndex="' + (nextIndex) + '"]');
if (nextElem) {
nextElem.focus();
}
}
});
formElements[i].setAttribute(procAttr, true); // Add attribute to prevent adding 2 listeners on same element
}
});
}
};
});
Event should be in HTML component (keypress) = "keyFocus($event)"
Method shoulb be like .ts file.
keyFocus(input1){
input1.srcElement.nextElementSibling.focus();
}
AngularJS already contains a light version of jQuery so you can as well use it...
http://docs.angularjs.org/api/angular.element
You could try something like this:
element.next().focus()

Closing only particular FancyBox when having multiple Fancybox

In a given page, I have multiple instances of Fancybox items that will show up an video when clicked on a link.
Apart from those, I have a function running every 5 seconds to get data from a URL and display another fancybox based on the return value.
The problem is that, as the setInterval function runs always, even if the actual video is played, it closes that video as I use $.fancybox.close().
All I wanted is to close only the fanybox identified by myModal.
This is the jQuery that I use.
$(document).ready(function() {
function myplugin() {
$.getJSON("get-status.php", function (data) {
$.each(data, function (key, status) {
if(status > 0) {
$("#myModal").fancybox().click();
}else{
$.fancybox.close(); // Works. But closes other open Fancybox if any
//$("#myModal").fancybox().close(); // Does not work
}
});
});
};
$(function() {
setInterval(function() { myplugin() }, 5000);
});
});
Well, I am not completely sure I understood your question, however since it's not very easy to know if #myModal is currently opened in fancybox (outside of the fancybox function itself), I would create a flag or switch that would be enabled from within a fancybox callback IF #myModal is the current element opened.
Then, from myplugin() I would validate if the switch is true (#myModal is the current element) and if so, close fancybox.
The script would look something like this (not tested because I don't really know what myplugin() does) :
// declare a switch to set if #myModal is open in fancybox
var myModal = false;
$(document).ready(function () {
function myplugin() {
$.getJSON("get-status.php", function (data) {
$.each(data, function (key, status) {
if (status > 0) {
$("#myModal").fancybox({
// use a callback to set the switch = true
afterShow: function () {
$(this.element).attr("id") == "myModal" ? myModal = true : myModal = false;
}
}).click();
} else {
// close fancybox if myModal == true
if (myModal) {
$.fancybox().close();
myModal = false; // reset switch ?
}
}
});
});
};
// you don't need $(function(){ }); since you have declaread .ready() above
setInterval(function () {
myplugin()
}, 5000);
});
I tried this below one and it worked.
$("#myModal").parents("div .fancybox-skin").hide();
Please advice if there any other better way to do this.

can I build a css class on the fly in tiny mce?

I'm using tiny mce, but I found it adds multiple spans with inline styles to the content for any applied style. Inline styles are not W3c Compliant, so must avoid inline css. Is it possible to create css class on the fly and apply to the selection, while editing content in tiny mce ?
Yes that is possible, but it took me some effort. What needs to be done is to write the class into the head of the editors iframe. Here is some example code which should work for IE,FF, Safari and point you into the right direction:
fonturl = "http://myfonts.com/arial.ttf"
csstext_to_add = '#font-face {font-family: "ownfont";src: url("'+fonturl+'");}'; // example
iframe_id = ed.id;
with(document.getElementById(iframe_id).contentWindow){
var h=document.getElementsByTagName("head");
if (!h.length) {
return;
}
var newStyleSheet=document.createElement("style");
newStyleSheet.type="text/css";
h[0].appendChild(newStyleSheet);
try{
if (typeof newStyleSheet.styleSheet !== "undefined") {
newStyleSheet.styleSheet.cssText = csstext_to_add;
}
else {
newStyleSheet.appendChild(document.createTextNode(csstext_to_add));
newStyleSheet.innerHTML=csstext_to_add;
}
}
catch(e){}
}
It is also possible to add that class as option into a dropdown (what takes some effort).
Thariama's answer was perfect. I'm using the tinyMCE jQuery connector for some of my pages and I have multiple instances of tinyMCE on the page. I made some modifications, but essentially its the same thing. I've created a text area field on the page that people can provide their own CSS. Also, I needed to change some CSS rules on the fly...
// function to change tinyMCE css on the fly
function checkCustomCSS() {
var $css = $('#page_css'),
newcss;
if ($css.val().length > 0) {
// since front end, we are wrapping their HTML in a wrapper and
// the tinyMCE edit iFrame is just using <body>, we need to change
// some rules so they can see the changes
newcss = $css.val().replace('#content_wrapper', 'body');
// loop through each tinyMCE editor and apply the code changes
// You could check the editor.id to make sure that the correct
// editor gets the appropriate changes.
$.each(tinyMCE.editors, function() {
var $this = $(this),
editorID = $this[0].id,
$ifrm = $('#' + editorID+ '_ifr'),
cwin, head, sheet;
if ($ifrm.length > 0 /* && editorID === 'OUR_EDITOR_ID_NAME' */) {
cwin = $ifrm[0].contentWindow;
head = cwin.document.getElementsByTagName("head");
if (!head.length) {
return;
}
sheet = cwin.document.createElement("style");
sheet.type = "text/css";
head[0].appendChild(sheet);
try {
if (typeof sheet.styleSheet !== "undefined") {
sheet.styleSheet.cssText = newcss;
} else {
sheet.appendChild(cwin.document.createTextNode(newcss));
sheet.innerHTML = newcss;
}
} catch (e) {}
}
});
}
}
Then in the tinyMCE init call I added and onInit call to setup changes to the #page_css , like this:
oninit: function() {
$('#page_css').on('change', function() {
checkCustomCSS();
});
}
Works like a charm.