diff --git a/dist/tool-box.js b/dist/tool-box.js index 761bbac..8d1e938 100644 --- a/dist/tool-box.js +++ b/dist/tool-box.js @@ -115,7 +115,7 @@ angular.module('jdalt.toolBox') options = (typeof options == 'boolean') ? { flushRequests: options } : options || {} - return function compile(scopeParams, overrideOptions) { + return angular.extend(function compile(scopeParams, overrideOptions) { scopeParams = scopeParams || {} var scope = $rootScope.$new() @@ -125,13 +125,20 @@ angular.module('jdalt.toolBox') var cloneAttachFn if (callOptions.attach) cloneAttachFn = function(clone) { clone.appendTo('body') } - var el = $compile(tmpl)(scope, cloneAttachFn) + var el = $compile(callOptions.template || compile.template)(scope, cloneAttachFn) scope.$digest() if (callOptions.flushRequests) $httpBackend.flush() + var innerScope = el.isolateScope() - return angular.extend({ scope: scope }, DomHelper(el)) - } + return angular.extend({ + scope: scope, + innerScope: innerScope, + ctrl: innerScope && (innerScope.$ctrl || innerScope.ctrl) + }, DomHelper(el)) + }, { + template: tmpl + }) } @@ -148,11 +155,36 @@ angular.module('jdalt.toolBox') function DomHelper(root) { + var booleanInputs = 'input[type=checkbox], input[type=radio], option' + function normalizeText(str) { if (typeof str !== 'string') throw new Error('normalizeWhitespace called with a non-string argument: ' + typeof str) return str.replace(/\s+/g, ' ').trim() } + function getVal(input) { + input = input.first() + return input.is(booleanInputs) ? input.prop(input.is('option') ? 'selected' : 'checked') : input.val() + } + function setVal(input, value) { + // input.focus() // triggers directive binding + input.filter(booleanInputs).each(setBooleanInput) + input.not(booleanInputs).val(value).triggerHandler('change')//.triggerHandler('blur') + + function setBooleanInput() { + var $input = angular.element(this) + var isOption = input.is('option') + var prop = isOption ? 'selected' : 'checked' + var $changer = isOption ? $input.parents('select') : $input + + var triggerChange = !!value !== $input.prop(prop) + $input.prop(prop, !!value) // Force attribute state for $setViewValue + if (!isOption) $input.triggerHandler('click') // Trigger click handler (will call $setViewValue) + if (triggerChange) $changer.triggerHandler('change') + // if (scope) scope.$digest() // just in case something is $watching + } + } + return { $el: root, // jQuery wrapped element @@ -229,13 +261,13 @@ angular.module('jdalt.toolBox') throw new Error('Element "'+ selector +'" not found to setInputValue') } - inputEl.val(inputVal).trigger('change') + setVal(inputEl, inputVal) return DomHelper(inputEl) }, val: function(value) { - if(arguments.length > 0) root.val(value).trigger('change') - return root.val() + if(arguments.length > 0) setVal(root, value) + return getVal(root) }, cssClasses: function() { @@ -395,10 +427,10 @@ angular.module('jdalt.toolBox') baseResourceFinder ) { - var DSHttpAdapter + var DS, DSHttpAdapter var resourceDefs = {} - if($injector.has('DS') && $injector.has('DS')) { - var DS = $injector.get('DS') + if($injector.has('DS') && $injector.get('DS')) { + DS = $injector.get('DS') DSHttpAdapter = $injector.get('DSHttpAdapter') resourceDefs = DS.definitions } @@ -438,7 +470,7 @@ angular.module('jdalt.toolBox') } function isPath(def) { - return def[0] == '/' + return /^(https?:)?\//i.test(def) } function urlFromPath(method, path, params) { @@ -464,7 +496,10 @@ angular.module('jdalt.toolBox') var resourceBase = baseResourceFinder(def) var path = DSHttpAdapter.getPath(method, resourceBase, params, { params: params }) - return completePath(method, path, params) // params gets mutated by getPath, parent params (for nested routes) get stripped out when they are used + path = completePath(method, path, params) // params gets mutated by getPath, parent params (for nested routes) get stripped out when they are used + var suffix = resourceBase.suffix + if (suffix && !~path.indexOf(suffix)) path = path.replace(/(\?.*)?$/, suffix + '$1') // this is done in each js-data-http method, yuck + return path } function omit(sourceObj, keys) { diff --git a/src/directive-helper.js b/src/directive-helper.js index 63f3b1e..03fda00 100644 --- a/src/directive-helper.js +++ b/src/directive-helper.js @@ -10,7 +10,7 @@ angular.module('jdalt.toolBox') options = (typeof options == 'boolean') ? { flushRequests: options } : options || {} - return function compile(scopeParams, overrideOptions) { + return angular.extend(function compile(scopeParams, overrideOptions) { scopeParams = scopeParams || {} var scope = $rootScope.$new() @@ -20,13 +20,20 @@ angular.module('jdalt.toolBox') var cloneAttachFn if (callOptions.attach) cloneAttachFn = function(clone) { clone.appendTo('body') } - var el = $compile(tmpl)(scope, cloneAttachFn) + var el = $compile(callOptions.template || compile.template)(scope, cloneAttachFn) scope.$digest() if (callOptions.flushRequests) $httpBackend.flush() - - return angular.extend({ scope: scope }, DomHelper(el)) - } + var innerScope = el.isolateScope() + + return angular.extend({ + scope: scope, + innerScope: innerScope, + ctrl: innerScope && (innerScope.$ctrl || innerScope.ctrl) + }, DomHelper(el)) + }, { + template: tmpl + }) } diff --git a/src/dom-helper.js b/src/dom-helper.js index 068db5c..ac52b4b 100644 --- a/src/dom-helper.js +++ b/src/dom-helper.js @@ -5,11 +5,36 @@ angular.module('jdalt.toolBox') function DomHelper(root) { + var booleanInputs = 'input[type=checkbox], input[type=radio], option' + function normalizeText(str) { if (typeof str !== 'string') throw new Error('normalizeWhitespace called with a non-string argument: ' + typeof str) return str.replace(/\s+/g, ' ').trim() } + function getVal(input) { + input = input.first() + return input.is(booleanInputs) ? input.prop(input.is('option') ? 'selected' : 'checked') : input.val() + } + function setVal(input, value) { + // input.focus() // triggers directive binding + input.filter(booleanInputs).each(setBooleanInput) + input.not(booleanInputs).val(value).triggerHandler('change')//.triggerHandler('blur') + + function setBooleanInput() { + var $input = angular.element(this) + var isOption = input.is('option') + var prop = isOption ? 'selected' : 'checked' + var $changer = isOption ? $input.parents('select') : $input + + var triggerChange = !!value !== $input.prop(prop) + $input.prop(prop, !!value) // Force attribute state for $setViewValue + if (!isOption) $input.triggerHandler('click') // Trigger click handler (will call $setViewValue) + if (triggerChange) $changer.triggerHandler('change') + // if (scope) scope.$digest() // just in case something is $watching + } + } + return { $el: root, // jQuery wrapped element @@ -86,13 +111,13 @@ angular.module('jdalt.toolBox') throw new Error('Element "'+ selector +'" not found to setInputValue') } - inputEl.val(inputVal).trigger('change') + setVal(inputEl, inputVal) return DomHelper(inputEl) }, val: function(value) { - if(arguments.length > 0) root.val(value).trigger('change') - return root.val() + if(arguments.length > 0) setVal(root, value) + return getVal(root) }, cssClasses: function() { diff --git a/src/request-helper.js b/src/request-helper.js index d1f91be..1f3eb10 100644 --- a/src/request-helper.js +++ b/src/request-helper.js @@ -23,10 +23,10 @@ angular.module('jdalt.toolBox') baseResourceFinder ) { - var DSHttpAdapter + var DS, DSHttpAdapter var resourceDefs = {} - if($injector.has('DS') && $injector.has('DS')) { - var DS = $injector.get('DS') + if($injector.has('DS') && $injector.get('DS')) { + DS = $injector.get('DS') DSHttpAdapter = $injector.get('DSHttpAdapter') resourceDefs = DS.definitions } @@ -66,7 +66,7 @@ angular.module('jdalt.toolBox') } function isPath(def) { - return def[0] == '/' + return /^(https?:)?\//i.test(def) } function urlFromPath(method, path, params) { @@ -92,7 +92,10 @@ angular.module('jdalt.toolBox') var resourceBase = baseResourceFinder(def) var path = DSHttpAdapter.getPath(method, resourceBase, params, { params: params }) - return completePath(method, path, params) // params gets mutated by getPath, parent params (for nested routes) get stripped out when they are used + path = completePath(method, path, params) // params gets mutated by getPath, parent params (for nested routes) get stripped out when they are used + var suffix = resourceBase.suffix + if (suffix && !~path.indexOf(suffix)) path = path.replace(/(\?.*)?$/, suffix + '$1') // this is done in each js-data-http method, yuck + return path } function omit(sourceObj, keys) { diff --git a/test/directive-helper-test.js b/test/directive-helper-test.js index 24c14e4..14d9395 100644 --- a/test/directive-helper-test.js +++ b/test/directive-helper-test.js @@ -21,6 +21,23 @@ describe('DirectiveHelper', function() { dom = compile(null, { attach: true }) expect(angular.element('#simp-main').length).toEqual(1) // angular.element searches from the body }) + + it('should allow overwriting the template on the compile function', function() { + compile.template = '